import type { XOTemplate } from '@xo-cash/types'; export const wrapBCHTemplate: XOTemplate = { $schema: 'https://libauth.org/schemas/wallet-template-v0.schema.json', name: 'Wrapped BCH', description: 'Convert between BCH and wBCH tokens.', icon: 'wrap', version: '1', supported: ['BCH_2023_05', 'BCH_2024_05', 'BCH_2025_05', 'BCH_2026_05'], roles: { user: { name: 'User', description: 'The person wrapping or unwrapping BCH.', icon: 'user', }, }, start: [ { action: 'wrap', role: 'user', }, { action: 'unwrap', role: 'user', }, ], actions: { wrap: { name: 'Wrap BCH', description: 'Convert BCH into wBCH tokens.', icon: 'wrap', roles: { user: { requirements: { variables: ['amountToWrap', 'recipientLockingScript'], }, }, }, requirements: { participants: [{ role: 'user', slots: { min: 1, max: 1 } }], }, transaction: 'wrapTransaction', }, unwrap: { name: 'Unwrap wBCH', description: 'Convert wBCH tokens back into BCH.', icon: 'unwrap', roles: { user: { requirements: { variables: ['amountToUnwrap', 'recipientLockingScript'], }, }, }, requirements: { participants: [{ role: 'user', slots: { min: 1, max: 1 } }], }, transaction: 'unwrapTransaction', }, }, transactions: { wrapTransaction: { name: 'Wrapped BCH', description: 'Wrapped $( OP_DIV).$( OP_MOD) BCH into wBCH tokens.', icon: 'wrap', inputs: [ { input: 'covenantInput', inputIndex: 0 }, ], outputs: [ { output: 'covenantOutput', outputIndex: 0 }, { output: 'wrappedTokensOutput', outputIndex: undefined }, ], version: 2, locktime: 0, composable: true, }, unwrapTransaction: { name: 'Unwrapped wBCH', description: 'Unwrapped $( OP_DIV).$( OP_MOD) wBCH tokens back into BCH.', icon: 'unwrap', inputs: [ { input: 'covenantInput', inputIndex: 0 }, ], outputs: [ { output: 'covenantOutput', outputIndex: 0 }, { output: 'unwrappedSatoshisOutput', outputIndex: undefined }, ], version: 2, locktime: 0, composable: true, }, }, outputs: { covenantOutput: { name: 'wBCH Covenant', description: 'Holds BCH and wBCH tokens that can be freely converted.', icon: 'contract', lockingScript: 'wrapBCHLockingScript', }, wrappedTokensOutput: { name: 'Wrapped wBCH', description: 'Wrapped $( OP_DIV).$( OP_MOD) wBCH tokens.', icon: 'receive', valueSatoshis: '$()', token: { category: '$()', amount: '$()', nft: null, }, roles: { user: { balance: { satoshis: true, fungibleTokens: true, nonfungibleTokens: true, }, selectable: true, }, }, lockingScript: '$()', }, unwrappedSatoshisOutput: { name: 'Unwrapped BCH', description: 'Unwrapped $( OP_DIV).$( OP_MOD) BCH.', icon: 'receive', valueSatoshis: '$()', token: null, roles: { user: { balance: { satoshis: true, fungibleTokens: true, nonfungibleTokens: true, }, selectable: true, }, }, lockingScript: '$()', }, }, inputs: { covenantInput: { name: 'wBCH Covenant', description: 'The covenant being updated.', icon: 'contract', unlockingScript: 'unlockCovenant', }, }, lockingScripts: { wrapBCHLockingScript: { name: 'wBCH Covenant', description: 'Holds BCH and wBCH tokens that can be freely converted.', icon: 'contract', lockingType: 'p2sh', lockingBytecode: 'wrapBCHLockingBytecode', actions: [ { action: 'wrap', role: 'user' }, { action: 'unwrap', role: 'user' }, ], state: { variables: [], secrets: [], }, balance: { satoshis: 0n, fungibleTokens: 0n, }, selectable: false, }, }, scripts: { enforceCovenantPersists: 'OP_INPUTINDEX OP_DUP OP_OUTPUTBYTECODE OP_SWAP OP_UTXOBYTECODE OP_EQUAL OP_VERIFY', enforceTokenCategoryPreserved: 'OP_INPUTINDEX OP_DUP OP_OUTPUTTOKENCATEGORY OP_SWAP OP_UTXOTOKENCATEGORY OP_EQUAL OP_VERIFY', enforceValueTokenSumConserved: 'OP_INPUTINDEX OP_UTXOVALUE OP_INPUTINDEX OP_UTXOTOKENAMOUNT OP_ADD OP_INPUTINDEX OP_OUTPUTVALUE OP_INPUTINDEX OP_OUTPUTTOKENAMOUNT OP_ADD OP_EQUAL OP_VERIFY', // Direct script references — introspection opcodes must not use $(...) evaluations // because those are evaluated at compile time without transaction context. wrapBCHLockingBytecode: 'enforceCovenantPersists enforceTokenCategoryPreserved enforceValueTokenSumConserved', unlockCovenant: '', }, constants: { wbchTokenCategory: { name: 'wBCH Token Category', description: 'The official token category for Wrapped BCH.', type: 'bytes', value: 'ff4d6e4b90aa8158d39c5dc874fd9411af1ac3b5ed6f354755e8362a0d02c6b3', }, satoshisPerBCH: { name: 'Satoshis per BCH', description: 'Used to display amounts in BCH with decimals.', type: 'integer', value: 100000000, }, tokenDust: { name: 'Token Dust Limit', description: 'Minimal satoshis required for a token-bearing output.', type: 'integer', value: 1000, }, }, variables: { amountToWrap: { name: 'Amount to Wrap', description: 'How much BCH to convert to wBCH (in satoshis).', type: 'integer', hint: 'satoshis', }, amountToUnwrap: { name: 'Amount to Unwrap', description: 'How much wBCH to convert back to BCH (in satoshis).', type: 'integer', hint: 'satoshis', }, recipientLockingScript: { name: 'Destination', description: 'Where to receive your BCH or wBCH tokens.', type: 'bytes', hint: 'lockingScript', }, }, icons: [ { name: 'wrap', hash: '0000000000000000000000' }, { name: 'unwrap', hash: '0000000000000000000000' }, { name: 'user', hash: '0000000000000000000000' }, { name: 'contract', hash: '0000000000000000000000' }, { name: 'receive', hash: '0000000000000000000000' }, ], };