@bsv/sdk
Version:
BSV Blockchain Software Development Kit
1,430 lines (1,230 loc) • 76.3 kB
text/typescript
import { WalletInterface, SecurityLevel } from '../Wallet.interfaces.js'
import WalletWire from './WalletWire.js'
import * as Utils from '../../primitives/utils.js'
import calls from './WalletWireCalls.js'
import Certificate from '../../auth/certificates/Certificate.js'
/**
* Processes incoming wallet calls received over a wallet wire, with a given wallet.
*/
export default class WalletWireProcessor implements WalletWire {
wallet: WalletInterface
constructor(wallet: WalletInterface) {
this.wallet = wallet
}
private decodeOutpoint(reader: Utils.Reader): string {
const txidBytes = reader.read(32)
const txid = Utils.toHex(txidBytes)
const index = reader.readVarIntNum()
return `${txid}.${index}`
}
private encodeOutpoint(outpoint: string): number[] {
const writer = new Utils.Writer()
const [txid, index] = outpoint.split('.')
writer.write(Utils.toArray(txid, 'hex'))
writer.writeVarIntNum(Number(index))
return writer.toArray()
}
async transmitToWallet(message: number[]): Promise<number[]> {
const messageReader = new Utils.Reader(message)
try {
// Read call code
const callCode = messageReader.readUInt8()
// Map call code to call name
const callName = calls[callCode] // calls is enum
if (callName === undefined || callName === '') {
// Invalid call code
throw new Error(`Invalid call code: ${callCode}`)
}
// Read originator length
const originatorLength = messageReader.readUInt8()
const originatorBytes = messageReader.read(originatorLength)
const originator = Utils.toUTF8(originatorBytes)
// Read parameters
const paramsReader = messageReader // Remaining bytes
switch (callName) {
case 'createAction': {
// Deserialize parameters from paramsReader
const args: any = {}
// Read description
const descriptionLength = paramsReader.readVarIntNum()
const descriptionBytes = paramsReader.read(descriptionLength)
args.description = Utils.toUTF8(descriptionBytes)
// tx
const inputBeefLength = paramsReader.readVarIntNum()
if (inputBeefLength >= 0) {
args.inputBEEF = paramsReader.read(inputBeefLength) // BEEF (Byte[])
} else {
args.inputBEEF = undefined
}
// Read inputs
const inputsLength = paramsReader.readVarIntNum()
if (inputsLength >= 0) {
args.inputs = []
for (let i = 0; i < inputsLength; i++) {
const input: any = {}
// outpoint
input.outpoint = this.decodeOutpoint(paramsReader)
// unlockingScript / unlockingScriptLength
const unlockingScriptLength = paramsReader.readVarIntNum()
if (unlockingScriptLength >= 0) {
const unlockingScriptBytes = paramsReader.read(
unlockingScriptLength
)
input.unlockingScript = Utils.toHex(unlockingScriptBytes)
} else {
input.unlockingScript = undefined
const unlockingScriptLengthValue = paramsReader.readVarIntNum()
input.unlockingScriptLength = unlockingScriptLengthValue
}
// inputDescription
const inputDescriptionLength = paramsReader.readVarIntNum()
const inputDescriptionBytes = paramsReader.read(
inputDescriptionLength
)
input.inputDescription = Utils.toUTF8(inputDescriptionBytes)
// sequenceNumber
const sequenceNumber = paramsReader.readVarIntNum()
if (sequenceNumber >= 0) {
input.sequenceNumber = sequenceNumber
} else {
input.sequenceNumber = undefined
}
args.inputs.push(input)
}
} else {
args.inputs = undefined
}
// Read outputs
const outputsLength = paramsReader.readVarIntNum()
if (outputsLength >= 0) {
args.outputs = []
for (let i = 0; i < outputsLength; i++) {
const output: any = {}
// lockingScript
const lockingScriptLength = paramsReader.readVarIntNum()
const lockingScriptBytes = paramsReader.read(lockingScriptLength)
output.lockingScript = Utils.toHex(lockingScriptBytes)
// satoshis
output.satoshis = paramsReader.readVarIntNum()
// outputDescription
const outputDescriptionLength = paramsReader.readVarIntNum()
const outputDescriptionBytes = paramsReader.read(
outputDescriptionLength
)
output.outputDescription = Utils.toUTF8(outputDescriptionBytes)
// basket
const basketLength = paramsReader.readVarIntNum()
if (basketLength >= 0) {
const basketBytes = paramsReader.read(basketLength)
output.basket = Utils.toUTF8(basketBytes)
} else {
output.basket = undefined
}
// customInstructions
const customInstructionsLength = paramsReader.readVarIntNum()
if (customInstructionsLength >= 0) {
const customInstructionsBytes = paramsReader.read(
customInstructionsLength
)
output.customInstructions = Utils.toUTF8(
customInstructionsBytes
)
} else {
output.customInstructions = undefined
}
// tags
const tagsLength = paramsReader.readVarIntNum()
if (tagsLength >= 0) {
output.tags = []
for (let j = 0; j < tagsLength; j++) {
const tagLength = paramsReader.readVarIntNum()
const tagBytes = paramsReader.read(tagLength)
const tag = Utils.toUTF8(tagBytes)
output.tags.push(tag)
}
} else {
output.tags = undefined
}
args.outputs.push(output)
}
} else {
args.outputs = undefined
}
// lockTime
const lockTime = paramsReader.readVarIntNum()
if (lockTime >= 0) {
args.lockTime = lockTime
} else {
args.lockTime = undefined
}
// version
const version = paramsReader.readVarIntNum()
if (version >= 0) {
args.version = version
} else {
args.version = undefined
}
// labels
const labelsLength = paramsReader.readVarIntNum()
if (labelsLength >= 0) {
args.labels = []
for (let i = 0; i < labelsLength; i++) {
const labelLength = paramsReader.readVarIntNum()
const labelBytes = paramsReader.read(labelLength)
const label = Utils.toUTF8(labelBytes)
args.labels.push(label)
}
} else {
args.labels = undefined
}
// options
const optionsPresent = paramsReader.readInt8()
if (optionsPresent === 1) {
args.options = {}
// signAndProcess
const signAndProcessFlag = paramsReader.readInt8()
if (signAndProcessFlag === -1) {
args.options.signAndProcess = undefined
} else {
args.options.signAndProcess = signAndProcessFlag === 1
}
// acceptDelayedBroadcast
const acceptDelayedBroadcastFlag = paramsReader.readInt8()
if (acceptDelayedBroadcastFlag === -1) {
args.options.acceptDelayedBroadcast = undefined
} else {
args.options.acceptDelayedBroadcast =
acceptDelayedBroadcastFlag === 1
}
// trustSelf
const trustSelfFlag = paramsReader.readInt8()
if (trustSelfFlag === -1) {
args.options.trustSelf = undefined
} else if (trustSelfFlag === 1) {
args.options.trustSelf = 'known'
}
// knownTxids
const knownTxidsLength = paramsReader.readVarIntNum()
if (knownTxidsLength >= 0) {
args.options.knownTxids = []
for (let i = 0; i < knownTxidsLength; i++) {
const txidBytes = paramsReader.read(32)
const txid = Utils.toHex(txidBytes)
args.options.knownTxids.push(txid)
}
} else {
args.options.knownTxids = undefined
}
// returnTXIDOnly
const returnTXIDOnlyFlag = paramsReader.readInt8()
if (returnTXIDOnlyFlag === -1) {
args.options.returnTXIDOnly = undefined
} else {
args.options.returnTXIDOnly = returnTXIDOnlyFlag === 1
}
// noSend
const noSendFlag = paramsReader.readInt8()
if (noSendFlag === -1) {
args.options.noSend = undefined
} else {
args.options.noSend = noSendFlag === 1
}
// noSendChange
const noSendChangeLength = paramsReader.readVarIntNum()
if (noSendChangeLength >= 0) {
args.options.noSendChange = []
for (let i = 0; i < noSendChangeLength; i++) {
const outpoint = this.decodeOutpoint(paramsReader)
args.options.noSendChange.push(outpoint)
}
} else {
args.options.noSendChange = undefined
}
// sendWith
const sendWithLength = paramsReader.readVarIntNum()
if (sendWithLength >= 0) {
args.options.sendWith = []
for (let i = 0; i < sendWithLength; i++) {
const txidBytes = paramsReader.read(32)
const txid = Utils.toHex(txidBytes)
args.options.sendWith.push(txid)
}
} else {
args.options.sendWith = undefined
}
// randomizeOutputs
const randomizeOutputsFlag = paramsReader.readInt8()
if (randomizeOutputsFlag === -1) {
args.options.randomizeOutputs = undefined
} else {
args.options.randomizeOutputs = randomizeOutputsFlag === 1
}
} else {
args.options = undefined
}
// Call the method
const createActionResult = await this.wallet.createAction(
args,
originator
)
// Serialize the result
const resultWriter = new Utils.Writer()
// txid
if (createActionResult.txid != null && createActionResult.txid !== '') {
resultWriter.writeInt8(1)
resultWriter.write(Utils.toArray(createActionResult.txid, 'hex'))
} else {
resultWriter.writeInt8(0)
}
// tx
if (createActionResult.tx != null) {
resultWriter.writeInt8(1)
resultWriter.writeVarIntNum(createActionResult.tx.length)
resultWriter.write(createActionResult.tx)
} else {
resultWriter.writeInt8(0)
}
// noSendChange
if (createActionResult.noSendChange != null) {
resultWriter.writeVarIntNum(createActionResult.noSendChange.length)
for (const outpoint of createActionResult.noSendChange) {
resultWriter.write(this.encodeOutpoint(outpoint))
}
} else {
resultWriter.writeVarIntNum(-1)
}
// sendWithResults
if (createActionResult.sendWithResults != null) {
resultWriter.writeVarIntNum(
createActionResult.sendWithResults.length
)
for (const result of createActionResult.sendWithResults) {
resultWriter.write(Utils.toArray(result.txid, 'hex'))
let statusCode
if (result.status === 'unproven') statusCode = 1
else if (result.status === 'sending') statusCode = 2
else if (result.status === 'failed') statusCode = 3
resultWriter.writeInt8(statusCode)
}
} else {
resultWriter.writeVarIntNum(-1)
}
// signableTransaction
if (createActionResult.signableTransaction != null) {
resultWriter.writeInt8(1)
resultWriter.writeVarIntNum(
createActionResult.signableTransaction.tx.length
)
resultWriter.write(createActionResult.signableTransaction.tx)
const referenceBytes = Utils.toArray(
createActionResult.signableTransaction.reference,
'base64'
)
resultWriter.writeVarIntNum(referenceBytes.length)
resultWriter.write(referenceBytes)
} else {
resultWriter.writeInt8(0)
}
// Return success code and result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.write(resultWriter.toArray())
return responseWriter.toArray()
}
case 'signAction': {
const args: any = {}
// Deserialize spends
const spendCount = paramsReader.readVarIntNum()
args.spends = {}
for (let i = 0; i < spendCount; i++) {
const inputIndex = paramsReader.readVarIntNum()
const spend: any = {}
// unlockingScript
const unlockingScriptLength = paramsReader.readVarIntNum()
const unlockingScriptBytes = paramsReader.read(
unlockingScriptLength
)
spend.unlockingScript = Utils.toHex(unlockingScriptBytes)
// sequenceNumber
const sequenceNumber = paramsReader.readVarIntNum()
if (sequenceNumber >= 0) {
spend.sequenceNumber = sequenceNumber
} else {
spend.sequenceNumber = undefined
}
args.spends[inputIndex] = spend
}
// Deserialize reference
const referenceLength = paramsReader.readVarIntNum()
const referenceBytes = paramsReader.read(referenceLength)
args.reference = Utils.toBase64(referenceBytes)
// Deserialize options
const optionsPresent = paramsReader.readInt8()
if (optionsPresent === 1) {
args.options = {}
// acceptDelayedBroadcast
const acceptDelayedBroadcastFlag = paramsReader.readInt8()
if (acceptDelayedBroadcastFlag === -1) {
args.options.acceptDelayedBroadcast = undefined
} else {
args.options.acceptDelayedBroadcast =
acceptDelayedBroadcastFlag === 1
}
// returnTXIDOnly
const returnTXIDOnlyFlag = paramsReader.readInt8()
if (returnTXIDOnlyFlag === -1) {
args.options.returnTXIDOnly = undefined
} else {
args.options.returnTXIDOnly = returnTXIDOnlyFlag === 1
}
// noSend
const noSendFlag = paramsReader.readInt8()
if (noSendFlag === -1) {
args.options.noSend = undefined
} else {
args.options.noSend = noSendFlag === 1
}
// sendWith
const sendWithLength = paramsReader.readVarIntNum()
if (sendWithLength >= 0) {
args.options.sendWith = []
for (let i = 0; i < sendWithLength; i++) {
const txidBytes = paramsReader.read(32)
const txid = Utils.toHex(txidBytes)
args.options.sendWith.push(txid)
}
} else {
args.options.sendWith = undefined
}
} else {
args.options = undefined
}
// Call the method
const signActionResult = await this.wallet.signAction(
args,
originator
)
// Serialize the result
const resultWriter = new Utils.Writer()
// txid
if (signActionResult.txid != null && signActionResult.txid !== '') {
resultWriter.writeInt8(1)
resultWriter.write(Utils.toArray(signActionResult.txid, 'hex'))
} else {
resultWriter.writeInt8(0)
}
// tx
if (signActionResult.tx != null) {
resultWriter.writeInt8(1)
resultWriter.writeVarIntNum(signActionResult.tx.length)
resultWriter.write(signActionResult.tx)
} else {
resultWriter.writeInt8(0)
}
// sendWithResults
if (signActionResult.sendWithResults != null) {
resultWriter.writeVarIntNum(
signActionResult.sendWithResults.length
)
for (const result of signActionResult.sendWithResults) {
resultWriter.write(Utils.toArray(result.txid, 'hex'))
let statusCode
if (result.status === 'unproven') statusCode = 1
else if (result.status === 'sending') statusCode = 2
else if (result.status === 'failed') statusCode = 3
resultWriter.writeInt8(statusCode)
}
} else {
resultWriter.writeVarIntNum(-1)
}
// Return success code and result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.write(resultWriter.toArray())
return responseWriter.toArray()
}
case 'abortAction': {
// Deserialize reference
const referenceBytes = paramsReader.read()
const reference = Utils.toBase64(referenceBytes)
// Call the method
await this.wallet.abortAction({ reference }, originator)
// Return success code and result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
return responseWriter.toArray()
}
case 'listActions': {
const args: any = {}
// Deserialize labels
const labelsLength = paramsReader.readVarIntNum()
args.labels = []
for (let i = 0; i < labelsLength; i++) {
const labelLength = paramsReader.readVarIntNum()
const labelBytes = paramsReader.read(labelLength)
args.labels.push(Utils.toUTF8(labelBytes))
}
// Deserialize labelQueryMode
const labelQueryModeFlag = paramsReader.readInt8()
if (labelQueryModeFlag === -1) {
args.labelQueryMode = undefined
} else if (labelQueryModeFlag === 1) {
args.labelQueryMode = 'any'
} else if (labelQueryModeFlag === 2) {
args.labelQueryMode = 'all'
}
// Deserialize include options
const includeOptionsNames = [
'includeLabels',
'includeInputs',
'includeInputSourceLockingScripts',
'includeInputUnlockingScripts',
'includeOutputs',
'includeOutputLockingScripts'
]
for (const optionName of includeOptionsNames) {
const optionFlag = paramsReader.readInt8()
if (optionFlag === -1) {
args[optionName] = undefined
} else {
args[optionName] = optionFlag === 1
}
}
// Deserialize limit
const limit = paramsReader.readVarIntNum()
if (limit >= 0) {
args.limit = limit
} else {
args.limit = undefined
}
// Deserialize offset
const offset = paramsReader.readVarIntNum()
if (offset >= 0) {
args.offset = offset
} else {
args.offset = undefined
}
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
const listActionsResult = await this.wallet.listActions(
args,
originator
)
// Serialize the result
const resultWriter = new Utils.Writer()
// totalActions
resultWriter.writeVarIntNum(listActionsResult.totalActions)
// actions
for (const action of listActionsResult.actions) {
// txid
resultWriter.write(Utils.toArray(action.txid, 'hex'))
// satoshis
resultWriter.writeVarIntNum(action.satoshis)
// status
let statusCode
switch (action.status) {
case 'completed':
statusCode = 1
break
case 'unprocessed':
statusCode = 2
break
case 'sending':
statusCode = 3
break
case 'unproven':
statusCode = 4
break
case 'unsigned':
statusCode = 5
break
case 'nosend':
statusCode = 6
break
case 'nonfinal':
statusCode = 7
break
case 'failed':
statusCode = 8
break
default:
statusCode = -1
break
}
resultWriter.writeInt8(statusCode)
// isOutgoing
resultWriter.writeInt8(action.isOutgoing ? 1 : 0)
// description
const descriptionBytes = Utils.toArray(action.description, 'utf8')
resultWriter.writeVarIntNum(descriptionBytes.length)
resultWriter.write(descriptionBytes)
// labels
if (action.labels !== undefined) {
resultWriter.writeVarIntNum(action.labels.length)
for (const label of action.labels) {
const labelBytes = Utils.toArray(label, 'utf8')
resultWriter.writeVarIntNum(labelBytes.length)
resultWriter.write(labelBytes)
}
} else {
resultWriter.writeVarIntNum(-1)
}
// version
resultWriter.writeVarIntNum(action.version)
// lockTime
resultWriter.writeVarIntNum(action.lockTime)
// inputs
if (action.inputs !== undefined) {
resultWriter.writeVarIntNum(action.inputs.length)
for (const input of action.inputs) {
// sourceOutpoint
resultWriter.write(this.encodeOutpoint(input.sourceOutpoint))
// sourceSatoshis
resultWriter.writeVarIntNum(input.sourceSatoshis)
// sourceLockingScript
if (input.sourceLockingScript !== undefined) {
const sourceLockingScriptBytes = Utils.toArray(
input.sourceLockingScript,
'hex'
)
resultWriter.writeVarIntNum(sourceLockingScriptBytes.length)
resultWriter.write(sourceLockingScriptBytes)
} else {
resultWriter.writeVarIntNum(-1)
}
// unlockingScript
if (input.unlockingScript !== undefined) {
const unlockingScriptBytes = Utils.toArray(
input.unlockingScript,
'hex'
)
resultWriter.writeVarIntNum(unlockingScriptBytes.length)
resultWriter.write(unlockingScriptBytes)
} else {
resultWriter.writeVarIntNum(-1)
}
// inputDescription
const inputDescriptionBytes = Utils.toArray(
input.inputDescription,
'utf8'
)
resultWriter.writeVarIntNum(inputDescriptionBytes.length)
resultWriter.write(inputDescriptionBytes)
// sequenceNumber
resultWriter.writeVarIntNum(input.sequenceNumber)
}
} else {
resultWriter.writeVarIntNum(-1)
}
// outputs
if (action.outputs !== undefined) {
resultWriter.writeVarIntNum(action.outputs.length)
for (const output of action.outputs) {
// outputIndex
resultWriter.writeVarIntNum(output.outputIndex)
// satoshis
resultWriter.writeVarIntNum(output.satoshis)
// lockingScript
if (output.lockingScript !== undefined) {
const lockingScriptBytes = Utils.toArray(
output.lockingScript,
'hex'
)
resultWriter.writeVarIntNum(lockingScriptBytes.length)
resultWriter.write(lockingScriptBytes)
} else {
resultWriter.writeVarIntNum(-1)
}
// spendable
resultWriter.writeInt8(output.spendable ? 1 : 0)
// outputDescription
const outputDescriptionBytes = Utils.toArray(
output.outputDescription,
'utf8'
)
resultWriter.writeVarIntNum(outputDescriptionBytes.length)
resultWriter.write(outputDescriptionBytes)
// basket
if (output.basket !== undefined) {
const basketBytes = Utils.toArray(output.basket, 'utf8')
resultWriter.writeVarIntNum(basketBytes.length)
resultWriter.write(basketBytes)
} else {
resultWriter.writeVarIntNum(-1)
}
// tags
if (output.tags !== undefined) {
resultWriter.writeVarIntNum(output.tags.length)
for (const tag of output.tags) {
const tagBytes = Utils.toArray(tag, 'utf8')
resultWriter.writeVarIntNum(tagBytes.length)
resultWriter.write(tagBytes)
}
} else {
resultWriter.writeVarIntNum(-1)
}
// customInstructions
if (output.customInstructions !== undefined) {
const customInstructionsBytes = Utils.toArray(
output.customInstructions,
'utf8'
)
resultWriter.writeVarIntNum(customInstructionsBytes.length)
resultWriter.write(customInstructionsBytes)
} else {
resultWriter.writeVarIntNum(-1)
}
}
} else {
resultWriter.writeVarIntNum(-1)
}
}
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.write(resultWriter.toArray())
return responseWriter.toArray()
}
case 'internalizeAction': {
const args: any = {}
// Read tx
const txLength = paramsReader.readVarIntNum()
args.tx = paramsReader.read(txLength)
// Read outputs
const outputsLength = paramsReader.readVarIntNum()
args.outputs = []
for (let i = 0; i < outputsLength; i++) {
const output: any = {}
// outputIndex
output.outputIndex = paramsReader.readVarIntNum()
// protocol
const protocolFlag = paramsReader.readUInt8()
if (protocolFlag === 1) {
output.protocol = 'wallet payment'
output.paymentRemittance = {}
// senderIdentityKey
const senderIdentityKeyBytes = paramsReader.read(33)
output.paymentRemittance.senderIdentityKey = Utils.toHex(
senderIdentityKeyBytes
)
// derivationPrefix
const derivationPrefixLength = paramsReader.readVarIntNum()
const derivationPrefixBytes = paramsReader.read(
derivationPrefixLength
)
output.paymentRemittance.derivationPrefix = Utils.toBase64(
derivationPrefixBytes
)
// derivationSuffix
const derivationSuffixLength = paramsReader.readVarIntNum()
const derivationSuffixBytes = paramsReader.read(
derivationSuffixLength
)
output.paymentRemittance.derivationSuffix = Utils.toBase64(
derivationSuffixBytes
)
} else if (protocolFlag === 2) {
output.protocol = 'basket insertion'
output.insertionRemittance = {}
// basket
const basketLength = paramsReader.readVarIntNum()
const basketBytes = paramsReader.read(basketLength)
output.insertionRemittance.basket = Utils.toUTF8(basketBytes)
// customInstructions
const customInstructionsLength = paramsReader.readVarIntNum()
if (customInstructionsLength >= 0) {
const customInstructionsBytes = paramsReader.read(
customInstructionsLength
)
output.insertionRemittance.customInstructions = Utils.toUTF8(
customInstructionsBytes
)
}
// tags
const tagsLength = paramsReader.readVarIntNum()
if (tagsLength > 0) {
output.insertionRemittance.tags = []
for (let j = 0; j < tagsLength; j++) {
const tagLength = paramsReader.readVarIntNum()
const tagBytes = paramsReader.read(tagLength)
output.insertionRemittance.tags.push(Utils.toUTF8(tagBytes))
}
} else {
output.insertionRemittance.tags = []
}
}
args.outputs.push(output)
}
const numberOfLabels = paramsReader.readVarIntNum()
if (numberOfLabels >= 0) {
args.labels = []
for (let i = 0; i < numberOfLabels; i++) {
const labelLength = paramsReader.readVarIntNum()
args.labels.push(Utils.toUTF8(paramsReader.read(labelLength)))
}
}
const descriptionLength = paramsReader.readVarIntNum()
args.description = Utils.toUTF8(paramsReader.read(descriptionLength))
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
await this.wallet.internalizeAction(args, originator)
// Return success code and result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
return responseWriter.toArray()
}
case 'listOutputs': {
const args: any = {}
// Deserialize basket
const basketLength = paramsReader.readVarIntNum()
const basketBytes = paramsReader.read(basketLength)
args.basket = Utils.toUTF8(basketBytes)
// Deserialize tags
const tagsLength = paramsReader.readVarIntNum()
if (tagsLength > 0) {
args.tags = []
for (let i = 0; i < tagsLength; i++) {
const tagLength = paramsReader.readVarIntNum()
const tagBytes = paramsReader.read(tagLength)
args.tags.push(Utils.toUTF8(tagBytes))
}
} else {
args.tags = undefined
}
// Deserialize tagQueryMode
const tagQueryModeFlag = paramsReader.readInt8()
if (tagQueryModeFlag === 1) {
args.tagQueryMode = 'all'
} else if (tagQueryModeFlag === 2) {
args.tagQueryMode = 'any'
} else {
args.tagQueryMode = undefined
}
// Deserialize include
const includeFlag = paramsReader.readInt8()
if (includeFlag === 1) {
args.include = 'locking scripts'
} else if (includeFlag === 2) {
args.include = 'entire transactions'
} else {
args.include = undefined
}
// Deserialize includeCustomInstructions
const includeCustomInstructionsFlag = paramsReader.readInt8()
if (includeCustomInstructionsFlag === -1) {
args.includeCustomInstructions = undefined
} else {
args.includeCustomInstructions =
includeCustomInstructionsFlag === 1
}
// Deserialize includeTags
const includeTagsFlag = paramsReader.readInt8()
if (includeTagsFlag === -1) {
args.includeTags = undefined
} else {
args.includeTags = includeTagsFlag === 1
}
// Deserialize includeLabels
const includeLabelsFlag = paramsReader.readInt8()
if (includeLabelsFlag === -1) {
args.includeLabels = undefined
} else {
args.includeLabels = includeLabelsFlag === 1
}
// Deserialize limit
const limit = paramsReader.readVarIntNum()
if (limit >= 0) {
args.limit = limit
} else {
args.limit = undefined
}
// Deserialize offset
const offset = paramsReader.readVarIntNum()
if (offset >= 0) {
args.offset = offset
} else {
args.offset = undefined
}
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
const listOutputsResult = await this.wallet.listOutputs(
args,
originator
)
// Serialize the result
const resultWriter = new Utils.Writer()
// totalOutputs
resultWriter.writeVarIntNum(listOutputsResult.totalOutputs)
// BEEF length and BEEF or -1
if (listOutputsResult.BEEF != null) {
resultWriter.writeVarIntNum(listOutputsResult.BEEF.length)
resultWriter.write(listOutputsResult.BEEF)
} else {
resultWriter.writeVarIntNum(-1)
}
// outputs
for (const output of listOutputsResult.outputs) {
// outpoint
resultWriter.write(this.encodeOutpoint(output.outpoint))
// satoshis
resultWriter.writeVarIntNum(output.satoshis)
// lockingScript
if (output.lockingScript !== undefined) {
const lockingScriptBytes = Utils.toArray(
output.lockingScript,
'hex'
)
resultWriter.writeVarIntNum(lockingScriptBytes.length)
resultWriter.write(lockingScriptBytes)
} else {
resultWriter.writeVarIntNum(-1)
}
// customInstructions
if (output.customInstructions !== undefined) {
const customInstructionsBytes = Utils.toArray(
output.customInstructions,
'utf8'
)
resultWriter.writeVarIntNum(customInstructionsBytes.length)
resultWriter.write(customInstructionsBytes)
} else {
resultWriter.writeVarIntNum(-1)
}
// tags
if (output.tags !== undefined) {
resultWriter.writeVarIntNum(output.tags.length)
for (const tag of output.tags) {
const tagBytes = Utils.toArray(tag, 'utf8')
resultWriter.writeVarIntNum(tagBytes.length)
resultWriter.write(tagBytes)
}
} else {
resultWriter.writeVarIntNum(-1)
}
// labels
if (output.labels !== undefined) {
resultWriter.writeVarIntNum(output.labels.length)
for (const label of output.labels) {
const labelBytes = Utils.toArray(label, 'utf8')
resultWriter.writeVarIntNum(labelBytes.length)
resultWriter.write(labelBytes)
}
} else {
resultWriter.writeVarIntNum(-1)
}
}
// Return success code and result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.write(resultWriter.toArray())
return responseWriter.toArray()
}
case 'relinquishOutput': {
const args: any = {}
// Deserialize basket
const basketLength = paramsReader.readVarIntNum()
const basketBytes = paramsReader.read(basketLength)
args.basket = Utils.toUTF8(basketBytes)
// Deserialize outpoint
args.output = this.decodeOutpoint(paramsReader)
// Call the method
await this.wallet.relinquishOutput(args, originator)
// Return success code and result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
return responseWriter.toArray()
}
case 'getPublicKey': {
const args: any = {}
// Deserialize identityKey flag
const identityKeyFlag = paramsReader.readUInt8()
args.identityKey = identityKeyFlag === 1
if (args.identityKey !== true) {
// Deserialize protocolID
args.protocolID = this.decodeProtocolID(paramsReader)
// Deserialize keyID
args.keyID = this.decodeString(paramsReader)
// Deserialize counterparty
args.counterparty = this.decodeCounterparty(paramsReader)
// Deserialize privilege parameters
const privilegedFlag = paramsReader.readInt8()
if (privilegedFlag === -1) {
args.privileged = undefined
} else {
args.privileged = privilegedFlag === 1
}
const privilegedReasonLength = paramsReader.readInt8()
if (privilegedReasonLength !== -1) {
const privilegedReasonBytes = paramsReader.read(
privilegedReasonLength
)
args.privilegedReason = Utils.toUTF8(privilegedReasonBytes)
} else {
args.privilegedReason = undefined
}
// Deserialize forSelf
const forSelfFlag = paramsReader.readInt8()
if (forSelfFlag === -1) {
args.forSelf = undefined
} else {
args.forSelf = forSelfFlag === 1
}
} else {
// Deserialize privilege parameters
const privilegedFlag = paramsReader.readInt8()
if (privilegedFlag === -1) {
args.privileged = undefined
} else {
args.privileged = privilegedFlag === 1
}
const privilegedReasonLength = paramsReader.readInt8()
if (privilegedReasonLength !== -1) {
const privilegedReasonBytes = paramsReader.read(
privilegedReasonLength
)
args.privilegedReason = Utils.toUTF8(privilegedReasonBytes)
} else {
args.privilegedReason = undefined
}
}
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
const getPublicKeyResult = await this.wallet.getPublicKey(
args,
originator
)
// Serialize the result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
const publicKeyBytes = Utils.toArray(
getPublicKeyResult.publicKey,
'hex'
)
responseWriter.write(publicKeyBytes)
return responseWriter.toArray()
}
case 'encrypt': {
const args: any = this.decodeKeyRelatedParams(paramsReader)
// Deserialize plaintext
const plaintextLength = paramsReader.readVarIntNum()
args.plaintext = paramsReader.read(plaintextLength)
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
const encryptResult = await this.wallet.encrypt(args, originator)
// Serialize the result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.write(encryptResult.ciphertext)
return responseWriter.toArray()
}
case 'decrypt': {
const args: any = this.decodeKeyRelatedParams(paramsReader)
// Deserialize ciphertext
const ciphertextLength = paramsReader.readVarIntNum()
args.ciphertext = paramsReader.read(ciphertextLength)
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
const decryptResult = await this.wallet.decrypt(args, originator)
// Serialize the result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.write(decryptResult.plaintext)
return responseWriter.toArray()
}
case 'createHmac': {
const args: any = this.decodeKeyRelatedParams(paramsReader)
// Deserialize data
const dataLength = paramsReader.readVarIntNum()
args.data = paramsReader.read(dataLength)
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
const createHmacResult = await this.wallet.createHmac(
args,
originator
)
// Serialize the result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.write(createHmacResult.hmac)
return responseWriter.toArray()
}
case 'verifyHmac': {
const args: any = this.decodeKeyRelatedParams(paramsReader)
// Deserialize hmac
args.hmac = paramsReader.read(32)
// Deserialize data
const dataLength = paramsReader.readVarIntNum()
args.data = paramsReader.read(dataLength)
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
await this.wallet.verifyHmac(args, originator)
// Serialize the result (no data to return)
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
return responseWriter.toArray()
}
case 'createSignature': {
const args: any = this.decodeKeyRelatedParams(paramsReader)
// Deserialize data or hashToDirectlySign
const dataTypeFlag = paramsReader.readUInt8()
if (dataTypeFlag === 1) {
const dataLength = paramsReader.readVarIntNum()
args.data = paramsReader.read(dataLength)
} else if (dataTypeFlag === 2) {
args.hashToDirectlySign = paramsReader.read(32)
}
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
const createSignatureResult = await this.wallet.createSignature(
args,
originator
)
// Serialize the result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.write(createSignatureResult.signature)
return responseWriter.toArray()
}
case 'verifySignature': {
const args: any = this.decodeKeyRelatedParams(paramsReader)
// Deserialize forSelf
const forSelfFlag = paramsReader.readInt8()
if (forSelfFlag === -1) {
args.forSelf = undefined
} else {
args.forSelf = forSelfFlag === 1
}
// Deserialize signature
const signatureLength = paramsReader.readVarIntNum()
args.signature = paramsReader.read(signatureLength)
// Deserialize data or hashToDirectlyVerify
const dataTypeFlag = paramsReader.readUInt8()
if (dataTypeFlag === 1) {
const dataLength = paramsReader.readVarIntNum()
args.data = paramsReader.read(dataLength)
} else if (dataTypeFlag === 2) {
args.hashToDirectlyVerify = paramsReader.read(32)
}
// Deserialize seekPermission
const seekPermission = paramsReader.readInt8()
if (seekPermission >= 0) {
args.seekPermission = seekPermission === 1
} else {
args.seekPermission = undefined
}
// Call the method
await this.wallet.verifySignature(args, originator)
// Serialize the result (no data to return)
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
return responseWriter.toArray()
}
case 'isAuthenticated': {
// No parameters to deserialize
// Call the method
const isAuthenticatedResult = await this.wallet.isAuthenticated(
{},
originator
)
// Serialize the result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.writeUInt8(
isAuthenticatedResult.authenticated ? 1 : 0
)
return responseWriter.toArray()
}
case 'waitForAuthentication': {
// No parameters to deserialize
// Call the method
await this.wallet.waitForAuthentication({}, originator)
// Serialize the result (authenticated is always true)
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
return responseWriter.toArray()
}
case 'getHeight': {
// No parameters to deserialize
// Call the method
const getHeightResult = await this.wallet.getHeight({}, originator)
// Serialize the result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
responseWriter.writeVarIntNum(getHeightResult.height)
return responseWriter.toArray()
}
case 'getHeaderForHeight': {
const args: any = {}
// Deserialize height
args.height = paramsReader.readVarIntNum()
// Call the method
const getHeaderResult = await this.wallet.getHeaderForHeight(
args,
originator
)
// Serialize the result
const responseWriter = new Utils.Writer()
responseWriter.writeUInt8(0) // errorByte = 0
const headerBytes = Utils.toArray(getHeaderResult.header, 'hex')
responseWriter.write(headerBytes)
return responseWriter.toArray()
}
case 'getNetwork': {
// No parameters to deserialize
// Call the method
const getNetworkResult = await this.wallet.getNetwork({}, originator)
// Serialize the result
const responseWriter = new Utils.W