Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 28x 28x 28x 28x 2x 2x 2x 2x 2x 2x 2x 28x 28x 2x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x | /* eslint-disable @typescript-eslint/no-unused-vars */
import * as bsv from '@bsv/sdk'
import { asBsvSdkScript, ScriptTemplateSABPPP, sdk } from "../.."
import { PendingSignAction, WalletSigner } from "../WalletSigner"
import { processActionSdk } from "./createActionSdk"
export async function signActionSdk(signer: WalletSigner, vargs: sdk.ValidSignActionArgs, originator?: sdk.OriginatorDomainNameStringUnder250Bytes)
: Promise<sdk.SignActionResult>
{
const prior = signer.pendingSignActions[vargs.reference]
Iif (!prior)
throw new sdk.WERR_NOT_IMPLEMENTED('recovery of out-of-session signAction reference data is not yet implemented.')
Iif (!prior.dcr.inputBeef)
throw new sdk.WERR_INTERNAL('prior.dcr.inputBeef must be valid')
prior.tx = await completeSignedTransaction(prior, vargs.spends, signer)
const sendWithResults = await processActionSdk(prior, signer, vargs, originator)
const r: sdk.SignActionResult = {
txid: prior.tx.id('hex'),
tx: vargs.options.returnTXIDOnly ? undefined : makeAtomicBeef(prior.tx, prior.dcr.inputBeef),
sendWithResults
}
return r
}
export function makeAtomicBeef(tx: bsv.Transaction, beef: number[] | bsv.Beef) : number[] {
Iif (Array.isArray(beef))
beef = bsv.Beef.fromBinary(beef)
beef.mergeTransaction(tx)
return beef.toBinaryAtomic(tx.id('hex'))
}
export async function completeSignedTransaction(
prior: PendingSignAction,
spends: Record<number, sdk.SignActionSpend>,
ninja: WalletSigner,
)
: Promise<bsv.Transaction>
{
/////////////////////
// Insert the user provided unlocking scripts from "spends" arg
/////////////////////
for (const [key, spend] of Object.entries(spends)) {
const vin = Number(key)
const createInput = prior.args.inputs[vin]
const input = prior.tx.inputs[vin]
Iif (!createInput || !input || createInput.unlockingScript || !Number.isInteger(createInput.unlockingScriptLength))
throw new sdk.WERR_INVALID_PARAMETER('args', `spend does not correspond to prior input with valid unlockingScriptLength.`)
Iif (spend.unlockingScript.length / 2 > createInput.unlockingScriptLength!)
throw new sdk.WERR_INVALID_PARAMETER('args', `spend unlockingScript length ${spend.unlockingScript.length} exceeds expected length ${createInput.unlockingScriptLength}`)
input.unlockingScript = asBsvSdkScript(spend.unlockingScript)
Iif (spend.sequenceNumber !== undefined)
input.sequence = spend.sequenceNumber
}
const results = {
sdk: <sdk.SignActionResult>{}
}
/////////////////////
// Insert SABPPP unlock templates for dojo signed inputs
/////////////////////
for (const pdi of prior.pdi) {
const sabppp = new ScriptTemplateSABPPP({
derivationPrefix: pdi.derivationPrefix,
derivationSuffix: pdi.derivationSuffix,
keyDeriver: ninja.keyDeriver
})
const keys = ninja.getClientChangeKeyPair()
const lockerPrivKey = keys.privateKey
const unlockerPubKey = pdi.unlockerPubKey || keys.publicKey
const sourceSatoshis = pdi.sourceSatoshis
const lockingScript = asBsvSdkScript(pdi.lockingScript)
const unlockTemplate = sabppp.unlock(lockerPrivKey, unlockerPubKey, sourceSatoshis, lockingScript)
const input = prior.tx.inputs[pdi.vin]
input.unlockingScriptTemplate = unlockTemplate
}
/////////////////////
// Sign dojo signed inputs making transaction fully valid.
/////////////////////
await prior.tx.sign()
return prior.tx
}
|