1395 lines
56 KiB
TypeScript
1395 lines
56 KiB
TypeScript
import type { XOTemplate } from '@xo-cash/types';
|
|
import { generateTemplateIdentifier } from '@xo-cash/engine';
|
|
|
|
export const p2pkhTemplate: XOTemplate = {
|
|
$schema: 'https://libauth.org/schemas/wallet-template-v0.schema.json',
|
|
|
|
// Name for this template.
|
|
name: 'Wallet (P2PKH)',
|
|
|
|
// Description for this template.
|
|
description: 'A standard single-factor wallet template that uses Pay-to-Public-Key-Hash (P2PKH) locking scripts.',
|
|
|
|
// Icon for this template.
|
|
icon: 'wallet',
|
|
|
|
// Version number for this template.
|
|
version: 0,
|
|
|
|
// List of VM versions that can be used to run this template.
|
|
supported: [ 'BCH_2023_05', 'BCH_2024_05', 'BCH_2025_05', 'BCH_2026_05' ],
|
|
|
|
// Describe a list of roles that are used in this template.
|
|
roles: {
|
|
owner: {
|
|
name: 'Wallet Owner',
|
|
description: 'The party who can spend from this wallet.',
|
|
icon: 'owner',
|
|
},
|
|
receiver: {
|
|
name: 'Receiver',
|
|
description: 'A party that is receiving value.',
|
|
icon: 'receiver',
|
|
},
|
|
sender: {
|
|
name: 'Sender',
|
|
description: 'A party that is sending value.',
|
|
icon: 'sender',
|
|
},
|
|
},
|
|
|
|
// Define a list of entrypoints supported by this template.
|
|
start: [
|
|
{
|
|
action: 'receive',
|
|
role: 'receiver',
|
|
},
|
|
{
|
|
action: 'requestSatoshis',
|
|
role: 'receiver',
|
|
},
|
|
{
|
|
action: 'requestFungibleTokens',
|
|
role: 'receiver',
|
|
},
|
|
{
|
|
action: 'requestNonfungibleTokens',
|
|
role: 'receiver',
|
|
},
|
|
],
|
|
|
|
// Define a list of actions that can be taken by this template.
|
|
// NOTE: There is no action to generate an address, but a wallet can create an invitation to a receive action and
|
|
// extract the generated lockscript as needed as the engine will track all lockscripts it generates.
|
|
actions: {
|
|
receive: {
|
|
// TODO: Consider rewriting to be generic/role-less.
|
|
name: 'Receive',
|
|
description: 'Receive an unspecified amount of cash and/or tokens from one or more senders.',
|
|
icon: 'receive',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Receive',
|
|
description: 'Receive an unspecified amount of cash and/or tokens from one or more senders.',
|
|
icon: 'receive',
|
|
|
|
requirements: {
|
|
generate: [ 'ownerKey' ],
|
|
},
|
|
},
|
|
sender: {
|
|
name: 'Send',
|
|
description: 'Send an unspecified amount of cash and/or tokens to the provided receiver.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'receiver',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
{
|
|
role: 'sender',
|
|
slots: { min: 1, max: undefined },
|
|
},
|
|
],
|
|
variables: [ 'requestedSatoshis' ],
|
|
},
|
|
|
|
transaction: 'receiveTransaction',
|
|
},
|
|
requestSatoshis: {
|
|
// TODO: Consider rewriting to be generic/role-less.
|
|
name: 'Request Satoshis',
|
|
description: 'Requests a specific amount of Bitcoin Cash from one or more senders.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Request Satoshis',
|
|
description: 'Requests a specific amount of Bitcoin Cash from one or more senders.',
|
|
icon: 'request',
|
|
|
|
requirements: {
|
|
generate: [ 'ownerKey' ],
|
|
variables: [ 'requestedSatoshis' ],
|
|
},
|
|
},
|
|
sender: {
|
|
name: 'Send',
|
|
description: 'Send a specific amount of Bitcoin Cash to the provided receiver.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'receiver',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
{
|
|
role: 'sender',
|
|
slots: { min: 1, max: undefined },
|
|
},
|
|
],
|
|
},
|
|
|
|
transaction: 'requestSatoshisTransaction',
|
|
},
|
|
requestFungibleTokens: {
|
|
// TODO: Consider rewriting to be generic/role-less.
|
|
name: 'Request Fungible Tokens',
|
|
description: 'Requests a specific amount of a fungible tokens from one or more senders.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Request Fungible Tokens',
|
|
description: 'Requests a specific amount of a fungible tokens from one or more senders.',
|
|
icon: 'request',
|
|
|
|
requirements: {
|
|
generate: [ 'ownerKey' ],
|
|
variables: [ 'requestedTokenCategory', 'requestedTokenAmount' ],
|
|
},
|
|
},
|
|
sender: {
|
|
name: 'Send',
|
|
description: 'Send a specific amount of fungible tokens to the provided receiver.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'receiver',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
{
|
|
role: 'sender',
|
|
slots: { min: 1, max: undefined },
|
|
},
|
|
],
|
|
},
|
|
|
|
transaction: 'requestFungibleTokensTransaction',
|
|
},
|
|
requestNonfungibleTokens: {
|
|
// TODO: Consider rewriting to be generic/role-less.
|
|
name: 'Request a Non-fungible Token',
|
|
description: 'Requests a non-fungible token from one or more senders.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Request a Non-fungible Token',
|
|
description: 'Requests a non-fungible token from one or more senders.',
|
|
icon: 'request',
|
|
|
|
requirements: {
|
|
generate: [ 'ownerKey' ],
|
|
variables: [ 'requestedTokenCategory', 'requestedTokenCapability', 'requestedTokenCommitment' ],
|
|
},
|
|
},
|
|
sender: {
|
|
name: 'Send',
|
|
description: 'Send a non-fungible token to the provided receiver.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'receiver',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
{
|
|
role: 'sender',
|
|
slots: { min: 1, max: undefined },
|
|
},
|
|
],
|
|
},
|
|
|
|
transaction: 'requestNonfungibleTokensTransaction',
|
|
},
|
|
|
|
// NOTE: Sending value can be done without explicit template support.
|
|
// NOTE: This feature is explicitly defined in this template to demonstrate how versatile templates can be, and
|
|
// to ensure the feature is discoverable by the user from outputs that hold value.
|
|
sendSatoshis: {
|
|
name: 'Send Satoshis',
|
|
description: 'Sends a specific amount of Bitcoin Cash to a given recipient.',
|
|
icon: 'send',
|
|
|
|
roles: {
|
|
sender: {
|
|
requirements: {
|
|
variables: [ 'transferredSatoshis', 'recipientLockingscript' ],
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'sender',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
],
|
|
},
|
|
|
|
// Sending is only available for outputs that have sufficient satoshis on them.
|
|
// NOTE: Dust is enforced here according to standardness rules.
|
|
condition: '$(OP_INPUTINDEX OP_UTXOVALUE <dustLimit> OP_GREATERTHAN)',
|
|
|
|
transaction: 'transferSatoshisTransaction',
|
|
},
|
|
sendFungibleTokens: {
|
|
name: 'Send Fungible Tokens',
|
|
description: 'Send a specific amount of a fungible token to a given recipient.',
|
|
icon: 'send',
|
|
|
|
roles: {
|
|
sender: {
|
|
requirements: {
|
|
variables: [ 'transferredTokenCategory', 'transferredTokenAmount', 'recipientLockingscript' ],
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'sender',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
],
|
|
},
|
|
|
|
// Sending is only available for outputs that have fungible tokens on them.
|
|
condition: '$(OP_INPUTINDEX OP_UTXOTOKENAMOUNT <0> OP_GREATERTHAN)',
|
|
|
|
transaction: 'transferFungibleTokensTransaction',
|
|
},
|
|
sendNonfungibleTokens: {
|
|
name: 'Send a Non-fungible Token',
|
|
description: 'Send a non-fungible token to a given recipient.',
|
|
icon: 'send',
|
|
|
|
roles: {
|
|
sender: {
|
|
requirements: {
|
|
variables: [ 'transferredTokenCategory', 'transferredTokenCapability', 'transferredTokenCommitment', 'recipientLockingscript' ],
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'sender',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
],
|
|
},
|
|
|
|
// Sending is only available for outputs that have a non-fungible token on them.
|
|
condition: '$(OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_SIZE OP_NIP <32> OP_GREATERTHAN)',
|
|
|
|
transaction: 'transferNonfungibleTokensTransaction',
|
|
},
|
|
|
|
// NOTE: Burning tokens can be done without explicit template support.
|
|
// NOTE: This feature is explicitly defined in this template to demonstrate how versatile templates can be, and
|
|
// to ensure the feature is discoverable by the user from outputs that hold tokens.
|
|
burnFungibleTokens: {
|
|
name: 'Delete Fungible Tokens',
|
|
description: 'Permanently and irreversibly deletes one or more fungible tokens.',
|
|
icon: 'burn',
|
|
|
|
roles: {
|
|
owner: {
|
|
requirements: {
|
|
variables: [ 'burnedTokenCategory', 'burnedTokenAmount' ],
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'owner',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
],
|
|
},
|
|
|
|
// Burning is only available for outputs that have fungible tokens on them.
|
|
condition: '$(OP_INPUTINDEX OP_UTXOTOKENAMOUNT <0> OP_GREATERTHAN)',
|
|
|
|
transaction: 'burnFungibleTokensTransaction',
|
|
},
|
|
burnNonfungibleTokens: {
|
|
name: 'Delete a Non-fungible Token',
|
|
description: 'Permanently and irreversibly deletes one non-fungible token.',
|
|
icon: 'burn',
|
|
|
|
roles: {
|
|
owner: {
|
|
requirements: {
|
|
variables: [ 'burnedTokenCategory', 'burnedTokenCapability', 'burnedTokenCommitment' ],
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'owner',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
],
|
|
},
|
|
|
|
// Burning is only available for outputs that have non-fungible tokens on them.
|
|
condition: '$(OP_INPUTINDEX OP_UTXOTOKENCATEGORY OP_SIZE OP_NIP <32> OP_GREATERTHAN)',
|
|
|
|
transaction: 'burnNonfungibleTokenTransaction',
|
|
},
|
|
|
|
sign: {
|
|
name: 'Sign Message',
|
|
description: 'Signs a provided message using the Bitcoin message signing protocol.',
|
|
icon: 'sign',
|
|
|
|
roles: {
|
|
owner: {
|
|
requirements: {
|
|
variables: [ 'messageToSign' ],
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'owner',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
],
|
|
},
|
|
|
|
data: [ 'messageSignature' ],
|
|
},
|
|
verify: {
|
|
name: 'Verify Message Signature',
|
|
description: 'Verifies a provided message signature according to the Bitcoin message signing protocol.',
|
|
icon: 'verify',
|
|
|
|
roles: {
|
|
owner: {
|
|
requirements: {
|
|
variables: [ 'messageSignature', 'messageToVerify' ],
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
},
|
|
},
|
|
|
|
requirements: {
|
|
roles: [
|
|
{
|
|
role: 'owner',
|
|
slots: { min: 1, max: 1 },
|
|
},
|
|
],
|
|
},
|
|
|
|
data: [ 'messageSignatureValidity' ],
|
|
},
|
|
},
|
|
|
|
// Define a set of data that can be used in this template.
|
|
data: {
|
|
messageSignature: {
|
|
// Evaluate CashASM expression to get the signature needed.
|
|
// NOTE: Pushes the prefix and message, then concatenates them together to form the data to sign.
|
|
// NOTE: In libauth today, it seems that this is done by defining the signature as a variable, and tying it to the key and message,
|
|
// and so this is different
|
|
// TODO: Check with Jason and see if there is any reason why this cannot be done like this.
|
|
value: '$(<messagePrefix> <message> OP_CAT <ownerKey.data_signature.top_stack_element>)',
|
|
type: 'bytes',
|
|
hint: 'signature',
|
|
},
|
|
messageSignatureValidity: {
|
|
// Evaluate the validity of the message with the owners public key.
|
|
value: '$(<messageSignature> <messagePrefix> <message> OP_CAT <ownerKey.public_key> OP_CHECKDATASIG)',
|
|
type: 'integer',
|
|
hint: 'script_boolean',
|
|
},
|
|
},
|
|
|
|
// Define a set of transactions that can be used in this template.
|
|
transactions: {
|
|
receiveTransaction: {
|
|
name: 'Transfer request',
|
|
description: 'Transfer request for an unspecified amount of cash and/or tokens.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description: 'Received an unspecified amount of cash and/or tokens.',
|
|
icon: 'receive',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description: 'Sent an unspecified amount of cash and/or tokens.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
// Inputs and outputs that must exist in the transaction.
|
|
// NOTE: There is no inputs required, but the engine should detect that there is not sufficient input value to
|
|
// match the output and thus generate an invitation to participate in this action.
|
|
// When the invitation is shared, the other parties can add as many inputs and change outputs as needed.
|
|
inputs: [],
|
|
outputs: [
|
|
{
|
|
output: 'receiveOutput',
|
|
index: undefined,
|
|
},
|
|
],
|
|
|
|
// Standard transaction without a locktime.
|
|
version: 2,
|
|
locktime: 0,
|
|
|
|
// ...
|
|
composable: true,
|
|
},
|
|
requestSatoshisTransaction: {
|
|
name: 'Transfer request',
|
|
description: 'Transfer request for $(<requestedSatoshis>) satoshis.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description: 'Received $(<requestedSatoshis>) satoshis.',
|
|
icon: 'receive',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description: 'Sent $(<requestedSatoshis>) satoshis.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
// Inputs and outputs that must exist in the transaction.
|
|
// NOTE: There is no inputs required, but the engine should detect that there is not sufficient input value to
|
|
// match the output and thus generate an invitation to participate in this action.
|
|
// When the invitation is shared, the other party can add as many inputs and outputs as needed since this transaction is composable.
|
|
inputs: [],
|
|
outputs: [
|
|
{
|
|
output: 'requestSatoshisOutput',
|
|
index: undefined,
|
|
},
|
|
],
|
|
|
|
// Standard transaction without a locktime.
|
|
version: 2,
|
|
locktime: 0,
|
|
|
|
// ...
|
|
composable: true,
|
|
},
|
|
requestFungibleTokensTransaction: {
|
|
name: 'Transfer request',
|
|
description:
|
|
'Transfer request for $(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_DIV).$(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_MOD) $(<requestedTokenCategory.symbol>) tokens.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description:
|
|
'Received $(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_DIV).$(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_MOD) $(<requestedTokenCategory.symbol>) tokens.',
|
|
icon: 'receive',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description:
|
|
'Sent $(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_DIV).$(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_MOD) $(<requestedTokenCategory.symbol>) tokens.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
// Inputs and outputs that must exist in the transaction.
|
|
// NOTE: There is no inputs required, but the engine should detect that there is not sufficient input value to
|
|
// match the output and thus generate an invitation to participate in this action.
|
|
// When the invitation is shared, the other party can add as many inputs and outputs as needed since this transaction is composable.
|
|
inputs: [],
|
|
outputs: [
|
|
{
|
|
output: 'requestFungibleTokensOutput',
|
|
index: undefined,
|
|
},
|
|
],
|
|
|
|
// Standard transaction without a locktime.
|
|
version: 2,
|
|
locktime: 0,
|
|
|
|
// ...
|
|
composable: true,
|
|
},
|
|
requestNonfungibleTokensTransaction: {
|
|
name: 'Transfer request',
|
|
description:
|
|
'Transfer request for one non-fungible $(<requestedTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <requestedTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) (<requestedTokenCategory.symbol>) token, with $(<requestedTokenCommitment>) commitment.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description:
|
|
'Received one non-fungible $(<requestedTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <requestedTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) (<requestedTokenCategory.symbol>) token, with $(<requestedTokenCommitment>) commitment.',
|
|
icon: 'receive',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description:
|
|
'Sent the requested non-fungible $(<requestedTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <requestedTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) (<requestedTokenCategory.symbol>) token, with $(<requestedTokenCommitment>) commitment.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
// Inputs and outputs that must exist in the transaction.
|
|
// NOTE: There is no inputs required, but the engine should detect that there is not sufficient input value to
|
|
// match the output and thus generate an invitation to participate in this action.
|
|
// When the invitation is shared, the other party can add as many inputs and outputs as needed since this transaction is composable.
|
|
inputs: [],
|
|
outputs: [
|
|
{
|
|
output: 'requestNonfungibleTokensOutput',
|
|
index: undefined,
|
|
},
|
|
],
|
|
|
|
// Standard transaction without a locktime.
|
|
version: 2,
|
|
locktime: 0,
|
|
|
|
// ...
|
|
composable: true,
|
|
},
|
|
|
|
transferSatoshisTransaction: {
|
|
name: 'Satoshis Transferred',
|
|
description: '$(<transferredSatoshis>) satoshis were transferred to a recipient.',
|
|
icon: 'send',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description: 'Received $(<transferredSatoshis>) satoshis.',
|
|
icon: 'receive',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description: 'Sent $(<transferredSatoshis>) satoshis.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
// Enforce the inputs and outputs required by the transaction.
|
|
// NOTE: The input is provided from the action since it is only available on outputs with satoshis.
|
|
inputs: [],
|
|
outputs: [
|
|
{
|
|
output: 'transferSatoshisOutput',
|
|
index: undefined,
|
|
},
|
|
],
|
|
|
|
// Standard transaction without a locktime.
|
|
version: 2,
|
|
locktime: 0,
|
|
|
|
// ...
|
|
composable: true,
|
|
},
|
|
transferFungibleTokensTransaction: {
|
|
name: 'Fungible Tokens Transferred',
|
|
description:
|
|
'$(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_DIV).$(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_MOD) $(<transferredTokenCategory.symbol>) tokens were transferred to a recipient.',
|
|
icon: 'send',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description:
|
|
'Received $(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_DIV).$(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_MOD) $(<transferredTokenCategory.symbol>) tokens.',
|
|
icon: 'receive',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description:
|
|
'Sent $(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_DIV).$(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_MOD) $(<transferredTokenCategory.symbol>) tokens.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
// Enforce the inputs and outputs required by the transaction.
|
|
// NOTE: The input is provided from the action since it is only available on outputs with fungible tokens.
|
|
inputs: [],
|
|
outputs: [
|
|
{
|
|
output: 'transferFungibleTokensOutput',
|
|
index: undefined,
|
|
},
|
|
],
|
|
|
|
// Standard transaction without a locktime.
|
|
version: 2,
|
|
locktime: 0,
|
|
|
|
// ...
|
|
composable: true,
|
|
},
|
|
transferNonfungibleTokensTransaction: {
|
|
name: 'Non-fungible Token Transferred',
|
|
description:
|
|
'One non-fungible $(<transferredTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <transferredTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) $(<transferredTokenCategory.symbol>) token was transferred to a recipient, with $(<transferredTokenCommitment>) commitment.',
|
|
icon: 'send',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description:
|
|
'Received one non-fungible $(<transferredTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <transferredTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) (<transferredTokenCategory.symbol>) token, with $(<transferredTokenCommitment>) commitment.',
|
|
icon: 'receive',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description:
|
|
'Sent one non-fungible $(<transferredTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <transferredTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) (<transferredTokenCategory.symbol>) token, with $(<transferredTokenCommitment>) commitment.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
// Enforce the inputs and outputs required by the transaction.
|
|
// NOTE: The input is provided from the action since it is only available on outputs with a non-fungible token.
|
|
inputs: [],
|
|
outputs: [
|
|
{
|
|
output: 'transferNonfungibleTokenOutput',
|
|
index: undefined,
|
|
},
|
|
],
|
|
|
|
// Standard transaction without a locktime.
|
|
version: 2,
|
|
locktime: 0,
|
|
|
|
// ...
|
|
composable: true,
|
|
},
|
|
|
|
burnFungibleTokensTransaction: {
|
|
name: 'Deleted fungible tokens',
|
|
description:
|
|
'Permanently and irreversibly deleted $(<burnedTokenAmount> <burnedTokenCategory.decimalsFactor> OP_DIV).$(<burnedTokenAmount> <burnedTokenCategory.decimalsFactor> OP_MOD) $(<burnedTokenCategory.symbol>) tokens.',
|
|
icon: 'burn',
|
|
|
|
// Inputs and outputs that must exist in the transaction.
|
|
// NOTE: There is no defined outputs as any non-burned value is automatically returned as change.
|
|
inputs: [
|
|
{
|
|
input: 'burnFungibleTokensInput',
|
|
index: undefined,
|
|
},
|
|
],
|
|
|
|
outputs: [],
|
|
|
|
// Standard transaction without a locktime.
|
|
version: 2,
|
|
locktime: 0,
|
|
|
|
// ...
|
|
composable: true,
|
|
},
|
|
burnNonfungibleTokenTransaction: {
|
|
name: 'Deleted non fungible token',
|
|
description:
|
|
'Permanently and irreversibly deleted a non-fungible $(<burnedTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <burnedTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) (<burnedTokenCategory.symbol>) token, with $(<burnedTokenCommitment>) commitment.',
|
|
icon: 'burn',
|
|
|
|
// Inputs and outputs that must exist in the transaction.
|
|
// NOTE: There is no defined outputs as any non-burned value is automatically returned as change.
|
|
inputs: [
|
|
{
|
|
input: 'burnNonfungibleTokenInput',
|
|
index: undefined,
|
|
},
|
|
],
|
|
outputs: [],
|
|
|
|
// Standard transaction without a locktime.
|
|
version: 2,
|
|
locktime: 0,
|
|
|
|
// ...
|
|
composable: true,
|
|
},
|
|
},
|
|
|
|
// Define a set of outputs that can be used within transactions in this template.
|
|
outputs: {
|
|
receiveOutput: {
|
|
name: 'Recipient output',
|
|
description: 'Transferred an unspecified amount of cash and/or tokens to a recipient.',
|
|
icon: 'receive',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description: 'Received an unspecified amount of cash and/or tokens.',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description: 'Sent an unspecified amount of cash and/or tokens.',
|
|
},
|
|
},
|
|
|
|
// Defines how the requested funds should be locked.
|
|
lockscript: 'receivingLockingScript',
|
|
},
|
|
requestSatoshisOutput: {
|
|
name: 'Recipient output',
|
|
description: 'Transferred $(<requestedSatoshis>) satoshis to a recipient.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description: 'Received $(<requestedSatoshis>) satoshis.',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description: 'Sent $(<requestedSatoshis>) satoshis.',
|
|
},
|
|
},
|
|
|
|
// Defines how the requested funds should be locked.
|
|
lockscript: 'receivingLockingScript',
|
|
|
|
// Require the specified number of satoshis and no tokens.
|
|
valueSatoshis: '$(<requestedSatoshis>)',
|
|
token: null,
|
|
},
|
|
requestFungibleTokensOutput: {
|
|
name: 'Recipient output',
|
|
description:
|
|
'Transferred $(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_DIV).$(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_MOD) $(<requestedTokenCategory.symbol>) tokens to a recipient.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description:
|
|
'Received $(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_DIV).$(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_MOD) $(<requestedTokenCategory.symbol>) tokens.',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description:
|
|
'Sent $(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_DIV).$(<requestedTokenAmount> <requestedTokenCategory.decimalsFactor> OP_MOD) $(<requestedTokenCategory.symbol>) tokens.',
|
|
},
|
|
},
|
|
|
|
// Defines how the requested funds should be locked.
|
|
lockscript: 'receivingLockingScript',
|
|
|
|
// Require a flat 1000 satoshis to ensure the fungible tokens remains transferrable.
|
|
valueSatoshis: '1000',
|
|
|
|
// Require only the specified amount and type of fungible tokens.
|
|
// NOTE: This can be composed with a request for a non-fungible token, but will always result in two separate outputs.
|
|
token: {
|
|
category: '$(<requestedTokenCategory>)',
|
|
amount: '$(<requestedTokenAmount>)',
|
|
nft: null,
|
|
},
|
|
},
|
|
requestNonfungibleTokensOutput: {
|
|
name: 'Recipient output',
|
|
description:
|
|
'Transferred one non-fungible $(<requestedTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <requestedTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) $(<requestedTokenCategory.symbol>) token to a recipient, with $(<requestedTokenCommitment>) commitment.',
|
|
icon: 'request',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description:
|
|
'Received one non-fungible $(<requestedTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <requestedTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) $(<requestedTokenCategory.symbol>) token, with $(<requestedTokenCommitment>) commitment.',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description:
|
|
'Sent the requested non-fungible $(<requestedTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <requestedTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) $(<requestedTokenCategory.symbol>) token, with $(<requestedTokenCommitment>) commitment.',
|
|
},
|
|
},
|
|
|
|
// Defines how the requested funds should be locked.
|
|
lockscript: 'receivingLockingScript',
|
|
|
|
// Require a flat 1000 satoshis to ensure the non-fungible token remains transferrable.
|
|
valueSatoshis: '1000',
|
|
|
|
// Require only an NFT with specified category, capability and commitment.
|
|
// NOTE: This can be composed with a request for fungible token amounts, but will always result in two separate outputs.
|
|
token: {
|
|
category: '$(<requestedTokenCategory>)',
|
|
amount: null,
|
|
nft: {
|
|
capability: '$(<requestedTokenCapability>)',
|
|
commitment: '$(<requestedTokenCommitment>)',
|
|
},
|
|
},
|
|
},
|
|
|
|
transferSatoshisOutput: {
|
|
name: 'Recipient output',
|
|
description: 'Transferred $(<transferredSatoshis>) satoshis to a recipient.',
|
|
icon: 'send',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description: 'Received $(<transferredSatoshis>) satoshis.',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description: 'Sent $(<transferredSatoshis>) satoshis.',
|
|
},
|
|
},
|
|
|
|
// Use the recipients lockscript.
|
|
lockscript: 'sendingLockingscript',
|
|
|
|
// Set the amount of satoshis to transfer.
|
|
valueSatoshis: '$(<transferredSatoshis>)',
|
|
},
|
|
transferFungibleTokensOutput: {
|
|
name: 'Recipient output',
|
|
description:
|
|
'Transferred $(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_DIV).$(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_MOD) $(<transferredTokenCategory.symbol>) tokens to a recipient.',
|
|
icon: 'send',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description:
|
|
'Received $(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_DIV).$(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_MOD) $(<transferredTokenCategory.symbol>) tokens.',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description:
|
|
'Sent $(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_DIV).$(<transferredTokenAmount> <transferredTokenCategory.decimalsFactor> OP_MOD) $(<transferredTokenCategory.symbol>) tokens.',
|
|
},
|
|
},
|
|
|
|
// Use the recipients lockscript.
|
|
lockscript: 'sendingLockingscript',
|
|
|
|
// Set the amount of fungible tokens to transfer.
|
|
token: {
|
|
category: '$(<transferredTokenCategory>)',
|
|
amount: '$(<transferredTokenAmount>)',
|
|
},
|
|
},
|
|
transferNonfungibleTokenOutput: {
|
|
name: 'Recipient output',
|
|
description:
|
|
'Transferred one non-fungible $(<transferredTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <transferredTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) $(<transferredTokenCategory.symbol>) token to a recipient, with $(<transferredTokenCommitment>) commitment.',
|
|
icon: 'send',
|
|
|
|
roles: {
|
|
receiver: {
|
|
name: 'Received',
|
|
description:
|
|
'Received one non-fungible $(<transferredTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <transferredTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) $(<transferredTokenCategory.symbol>) token, with $(<transferredTokenCommitment>) commitment.',
|
|
},
|
|
sender: {
|
|
name: 'Sent',
|
|
description:
|
|
'Sent one non-fungible $(<transferredTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <transferredTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) $(<transferredTokenCategory.symbol>) token, with $(<transferredTokenCommitment>) commitment.',
|
|
},
|
|
},
|
|
|
|
// Use the recipients lockscript.
|
|
lockscript: 'sendingLockingscript',
|
|
|
|
// Set the non-fungible token to transfer.
|
|
token: {
|
|
category: '$(<transferredTokenCategory>)',
|
|
nft: {
|
|
capability: '$(<transferredTokenCapability>)',
|
|
commitment: '$(<transferredTokenCommitment>)',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
inputs: {
|
|
burnFungibleTokensInput: {
|
|
name: 'Deleted fungible tokens',
|
|
description: 'Permanently and irreversibly deleted $(<burnedTokenAmount>) $(<burnedTokenCategory>).',
|
|
icon: 'burn',
|
|
|
|
// Define which unlocking script unlocks this input.
|
|
unlockingScript: 'unlockP2PKH',
|
|
|
|
// Require a fungible token of the requested token category, with an amount larger than or equal to the requested amount to burn.
|
|
token: {
|
|
category: '$(<burnedTokenCategory>)',
|
|
amount: '$(<this.fungibleTokenAmount> <burnedTokenAmount> OP_GREATERTHANOREQUAL OP_IF <this.fungibleTokens> OP_ENDIF)',
|
|
},
|
|
|
|
// Ignore the burned token amount when determining change for this output.
|
|
// NOTE: The engine must check that this does not exceed the input value.
|
|
omitChangeAmounts: {
|
|
fungibleTokens: '${<burnedTokenAmount>}',
|
|
},
|
|
},
|
|
burnNonfungibleTokenInput: {
|
|
name: 'Deleted non-fungible token',
|
|
description:
|
|
'Permanently and irreversibly burned one non-fungible $(<burnedTokenCapability> <0x02> OP_EQUAL OP_IF <"minting"> OP_ELSE <burnedTokenCapability> <0x01> OP_EQUAL OP_IF <"mutable"> OP_ELSE <"immutable"> OP_ENDIF OP_ENDIF) token of category $(<burnedTokenCategory>), with a $(<burnedTokenCommitment>) commitment.',
|
|
icon: 'burn',
|
|
|
|
// Define which unlocking script unlocks this input.
|
|
unlockingScript: 'unlockP2PKH',
|
|
|
|
// Require a non-fungible token of the specified category, capability and commitment to burn.
|
|
token: {
|
|
category: '$(<burnedTokenCategory>)',
|
|
nft: {
|
|
capability: '$(<burnedTokenCapability>)',
|
|
commitment: '$(<burnedTokenCommitment>)',
|
|
},
|
|
},
|
|
|
|
// Ignore the burned token when determining change for this output.
|
|
// NOTE: The engine must check that this does not exceed the input value.
|
|
omitChangeAmounts: {
|
|
nonfungibleTokens: 1,
|
|
},
|
|
},
|
|
},
|
|
|
|
// Define locking scripts used by this template.
|
|
// NOTE: Template supported wallets should automatically track all generated lockscripts for on-chain events.
|
|
lockingScripts: {
|
|
sendingLockingscript: {
|
|
// TODO: This currently describes outputs locked to this script, but all actions creating such outputs already have descriptions.
|
|
// This can either be dropped, or maybe more importantly, should be disambiguated so that lockscripts can provide separate
|
|
// descriptions for their script and the outputs that are locked to them. Leaving as a TODO for now and will address later.
|
|
name: 'Sent',
|
|
description: 'Funds sent to an external recipient',
|
|
icon: 'address',
|
|
|
|
// ...
|
|
lockingType: 'standard',
|
|
lockingScript: 'lockToRecipient',
|
|
|
|
// Indicate that the sent output does not belong to the initiating user.
|
|
// NOTE: These values default to false/empty, but added here for additional clarity.
|
|
actions: [],
|
|
state: [],
|
|
secrets: [],
|
|
balance: false,
|
|
selectable: false,
|
|
privacy: false,
|
|
},
|
|
receivingLockingScript: {
|
|
// NOTE: Outputs to this lockscript by external actors defaults to this description when detected on-chain.
|
|
name: 'Received',
|
|
description: 'Funds received without wallet coordination.',
|
|
icon: 'address',
|
|
|
|
// Defines how spending future received funds should be locked.
|
|
lockingType: 'standard',
|
|
lockingScript: 'lockP2PKH',
|
|
|
|
// Define a default unlocking script to be used when no action provided script is present.
|
|
unlockingScript: 'unlockP2PKH',
|
|
|
|
roles: {
|
|
receiver: {
|
|
// The only state that is required to be persisted when receiving funds is the owners private key.
|
|
// NOTE: This is defined as a secret to not leak when creating invitations for others to participate in request or send actions.
|
|
state: {
|
|
variables: [],
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
|
|
// List actions that can be taken with the ownerKey for each address/lockscript.
|
|
actions: [
|
|
{
|
|
action: 'sign',
|
|
role: 'owner',
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
{
|
|
action: 'verify',
|
|
role: 'owner',
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
{
|
|
action: 'sendSatoshis',
|
|
role: 'sender',
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
{
|
|
action: 'sendFungibleTokens',
|
|
role: 'sender',
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
{
|
|
action: 'sendNonfungibleTokens',
|
|
role: 'sender',
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
{
|
|
action: 'burnFungibleTokens',
|
|
role: 'sender',
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
{
|
|
action: 'burnNonfungibleTokens',
|
|
role: 'sender',
|
|
secrets: [ 'ownerKey' ],
|
|
},
|
|
],
|
|
|
|
// Indicates how much of received funds should be part of a wallets total balance.
|
|
// NOTE: Evaluates in the context of the source transaction, with the current outputs technical data available under this.output.*
|
|
// NOTE: This can either evaluate to a boolean or a number. If evaluated to a boolean, then true means 100% of the output.
|
|
// NOTE: Since we know that the owner controls all assets, we short-cut the evaluations by setting true directly.
|
|
balance: {
|
|
satoshis: true,
|
|
fungibleTokens: true,
|
|
// nonFungibleToken: true,
|
|
},
|
|
|
|
// Indicate when received funds should be considered in automatic coin selection to meet input requirements of other transactions.
|
|
// NOTE: Evaluates in the context of the source transaction, with the current outputs technical data available under this.output.*
|
|
// NOTE: This evaluates to a boolean. If non-true, the output should not be considered for automatic coin selection.
|
|
// NOTE: Since we know that the secret key exist for the owner, this template short-cuts the evaluation by setting true directly.
|
|
selectable: true,
|
|
|
|
// Indicate that received funds are not considered good privacy.
|
|
// NOTE: This information allows wallets to make better privacy decisions, like avoid mixing private and non-private outputs.
|
|
privacy: false,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
// Define a set of scripts that can be used in this template.
|
|
scripts: {
|
|
lockP2PKH: 'OP_DUP OP_HASH160 <$(<ownerKey.public_key> OP_HASH160)> OP_EQUALVERIFY OP_CHECKSIG',
|
|
unlockP2PKH: '<ownerKey.schnorr_signature.all_outputs> <ownerKey.public_key>',
|
|
lockToRecipient: '<recipientLockingscript>',
|
|
},
|
|
|
|
// TODO: Add icons
|
|
constants: {
|
|
dustLimit: {
|
|
name: 'Dust Limit',
|
|
description: 'Standard required minimum satoshis for Pay to Public Key Hash outputs.',
|
|
type: 'integer',
|
|
value: 546,
|
|
},
|
|
|
|
// Define a message prefix for use in arbitrary message signing.
|
|
messagePrefix: {
|
|
name: 'Message Prefix',
|
|
description: 'Standard message prefix used in the bitcoin signed message protocol.',
|
|
type: 'bytes',
|
|
|
|
// Value is enforced to the bitcoin signing magic string:
|
|
// "\x18Bitcoin Signed Message:\n"
|
|
value: '0x18426974636f696e205369676e6564204d6573736167653a0a',
|
|
},
|
|
},
|
|
|
|
// TODO: Add icons
|
|
variables: {
|
|
// Describe the secret private key.
|
|
ownerKey: {
|
|
name: 'Owners Private Key',
|
|
description: 'The private key used to authorize spending of received funds.',
|
|
type: 'bytes',
|
|
hint: 'private_key',
|
|
},
|
|
|
|
messageToSign: {
|
|
name: 'Message',
|
|
description: 'The text message to sign.',
|
|
type: 'string',
|
|
},
|
|
messageToVerify: {
|
|
name: 'Message',
|
|
description: 'The text message to verify.',
|
|
type: 'string',
|
|
},
|
|
messageSignature: {
|
|
name: 'Message Signature',
|
|
description: 'The signature for the message.',
|
|
type: 'bytes',
|
|
hint: 'signature',
|
|
},
|
|
|
|
// Describe the parameters used when requesting value.
|
|
requestedSatoshis: {
|
|
name: 'Requested Amount',
|
|
description: 'The Bitcoin Cash amount requested',
|
|
type: 'integer',
|
|
hint: 'satoshis',
|
|
},
|
|
requestedTokenCategory: {
|
|
name: 'Requested Token Category',
|
|
description: 'The token category requested',
|
|
type: 'bytes',
|
|
hint: 'token_category',
|
|
},
|
|
requestedTokenAmount: {
|
|
name: 'Requested Token Amount',
|
|
description: 'The fungible token amount requested',
|
|
type: 'integer',
|
|
hint: 'token_amount',
|
|
},
|
|
requestedTokenCapability: {
|
|
name: 'Requested Token Capability',
|
|
description: 'The non-fungible token capability requested',
|
|
type: 'bytes',
|
|
hint: 'token_capability',
|
|
},
|
|
requestedTokenCommitment: {
|
|
name: 'Requested Token Commitment',
|
|
description: 'The non-fungible token commitment requested',
|
|
type: 'bytes',
|
|
hint: 'token_commitment',
|
|
},
|
|
transferredTokenCategory: {
|
|
name: 'Sending Token Category',
|
|
description: 'The token category of the token(s) to send',
|
|
type: 'bytes',
|
|
hint: 'token_category',
|
|
},
|
|
transferredTokenAmount: {
|
|
name: 'Sending Token Amount',
|
|
description: 'The fungible token amount to send',
|
|
type: 'integer',
|
|
hint: 'token_amount',
|
|
},
|
|
transferredTokenCapability: {
|
|
name: 'Sending Token Capability',
|
|
description: 'The token capability for the non-fungible token to send',
|
|
type: 'bytes',
|
|
hint: 'token_capability',
|
|
},
|
|
transferredTokenCommitment: {
|
|
name: 'Sending Token Commitment',
|
|
description: 'The token commitment for the non-fungible token to send',
|
|
type: 'bytes',
|
|
hint: 'token_commitment',
|
|
},
|
|
burnedTokenCategory: {
|
|
name: 'Deleted Token Category',
|
|
description: 'The token category of the token(s) to delete',
|
|
type: 'bytes',
|
|
hint: 'token_category',
|
|
},
|
|
burnedTokenAmount: {
|
|
name: 'Deleted Token Amount',
|
|
description: 'The fungible token amount to delete',
|
|
type: 'integer',
|
|
hint: 'token_amount',
|
|
},
|
|
burnedTokenCapability: {
|
|
name: 'Deleted Token Capability',
|
|
description: 'The token capability for the non-fungible token to delete',
|
|
type: 'bytes',
|
|
hint: 'token_capability',
|
|
},
|
|
burnedTokenCommitment: {
|
|
name: 'Deleted Token Commitment',
|
|
description: 'The token commitment for the non-fungible token to delete',
|
|
type: 'bytes',
|
|
hint: 'token_commitment',
|
|
},
|
|
},
|
|
|
|
// Define a list of re-usable icons that can be used as part of metadata.
|
|
// NOTE: the actual icons are not embedded in the template but only referenced by hashes here,
|
|
// and can be distributed either as an asset pack or looked up through something like IPFS.
|
|
icons: [
|
|
{
|
|
name: 'wallet',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
{
|
|
name: 'owner',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
{
|
|
name: 'sender',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
{
|
|
name: 'address',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
{
|
|
name: 'receive',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
{
|
|
name: 'request',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
{
|
|
name: 'send',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
{
|
|
name: 'burn',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
{
|
|
name: 'sign',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
{
|
|
name: 'verify',
|
|
hash: '0000000000000000000000',
|
|
},
|
|
],
|
|
|
|
scenarios: [
|
|
{
|
|
name: 'requesting satoshis',
|
|
description: 'happy-path evaluation for requesting satoshis.',
|
|
|
|
// The action being run in the scenario.
|
|
action: 'requestSatoshis',
|
|
|
|
// List of roles taken in this scenario, and the resources they provided.
|
|
roles: [
|
|
{
|
|
role: 'receiver',
|
|
values: {
|
|
generated: {
|
|
ownerKey: 'KyRQa5pEXuzVcDwnXRLpYAascjchQW5DoxVRMbj4DTxS83573mz8',
|
|
},
|
|
variables: {
|
|
requestedSatoshis: 2000,
|
|
},
|
|
secrets: {
|
|
// This scenario does not carry any secrets.
|
|
},
|
|
inputs: [],
|
|
outputs: [
|
|
{
|
|
lockingBytecode: '76a91475c715ecb74178fe87933e57e947e5e92d904b8188ac',
|
|
valueSatoshis: 2000,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
role: 'sender',
|
|
values: {
|
|
// The sender provides no raw data to the action.
|
|
generated: {},
|
|
variables: {},
|
|
secrets: {},
|
|
|
|
// The sender does provide input and change.
|
|
inputs: [
|
|
{
|
|
outpointTransactionHash: '4ef28553a31a266719e66ba97fee3aeecd6d1788f7ff6ab12f8ebceda49660c0',
|
|
outpointIndex: 0,
|
|
sequenceNumber: 0,
|
|
unlockingBytecode:
|
|
'41226b2be7c2890c8bbde2f79e79640e56d866843f2e822ec51c469019d13db04a422c9ee49f5eefd26fee24e91910edbbb032b90cc54c34da80a61e69b0ee3d22412103e7ab26c36a7c7f45b2c26f33c08b0fa43a633268700f47216646d4cb37ae5696',
|
|
},
|
|
],
|
|
outputs: [
|
|
{
|
|
lockingBytecode: '76a91475c715ecb74178fe87933e57e947e5e92d904b8188ac',
|
|
valueSatoshis: 2000,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
|
|
// List of resources provided outside the context of a role.
|
|
values: {
|
|
generated: {
|
|
// This scenario does not have any non-role generated values.
|
|
},
|
|
variables: {
|
|
// This scenario does not have any non-role variables.
|
|
},
|
|
secrets: {
|
|
// This scenario does not have any non-role secrets.
|
|
},
|
|
},
|
|
|
|
// Outcomes provides the set of resulting values created from the action.
|
|
outcome: {
|
|
roles: {
|
|
receiver: {
|
|
name: 'Request',
|
|
description: 'Requested a specific amount of satoshis from one or more senders.',
|
|
icon: 'request',
|
|
},
|
|
sender: {
|
|
name: 'Send',
|
|
description: 'Sent a specific amount of satoshis to the provided receiver.',
|
|
icon: 'send',
|
|
},
|
|
},
|
|
|
|
transactions: [
|
|
{
|
|
transaction:
|
|
'0200000001c06096a4edbc8e2fb16afff788176dcdee3aee7fa96be61967261aa35385f24e000000006441226b2be7c2890c8bbde2f79e79640e56d866843f2e822ec51c469019d13db04a422c9ee49f5eefd26fee24e91910edbbb032b90cc54c34da80a61e69b0ee3d22412103e7ab26c36a7c7f45b2c26f33c08b0fa43a633268700f47216646d4cb37ae5696000000000267530300000000001976a91475c715ecb74178fe87933e57e947e5e92d904b8188acd0070000000000001976a91475c715ecb74178fe87933e57e947e5e92d904b8188ac00000000',
|
|
value: '',
|
|
},
|
|
],
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
export const p2pkhTemplateIdentifier = generateTemplateIdentifier(p2pkhTemplate); |