Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: transaction template #808

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cbb5490
feat: POC implementation
r4mmer Nov 11, 2024
9755aa8
feat: initial implementation
r4mmer Nov 11, 2024
a342ab7
feat: add support for create token transaction
r4mmer Dec 16, 2024
edb3894
feat: add balance management for created token reference
r4mmer Dec 17, 2024
250105d
tests: instruction tests
r4mmer Dec 20, 2024
90dab94
feat: complete instruction
r4mmer Dec 23, 2024
13efa80
feat: complete instruction
r4mmer Dec 23, 2024
fec87f6
feat: executor tests
r4mmer Dec 26, 2024
fff192b
tests: executor and interpreter tests
r4mmer Dec 26, 2024
d46c571
tests(integration): custom token integration template tests
r4mmer Dec 26, 2024
6f91f9e
chore: linter changes
r4mmer Dec 27, 2024
3a3b9ea
chore: linter changes
r4mmer Dec 27, 2024
30f1764
tests(integration): change injectFunds options
r4mmer Dec 27, 2024
3b2ae37
tests(integration): create token tx have different serialization
r4mmer Dec 27, 2024
7099194
tests(integration): include change outputs in checks
r4mmer Dec 27, 2024
edd8234
tests(integration): change output orderr
r4mmer Dec 27, 2024
d120896
tests(integration): add change value to send operation
r4mmer Dec 27, 2024
a50620a
chore: remove helper types to use inferred types from zod
r4mmer Dec 27, 2024
ee5edf4
tests(integration): add change and complete tests
r4mmer Dec 27, 2024
ab0b78e
tests(integration): wrong complete instruction type
r4mmer Dec 30, 2024
49ad6d3
fix: change would add invalid tokens on transaction
r4mmer Dec 31, 2024
674aa2d
tests(unit): mock balance properly
r4mmer Dec 31, 2024
c7e968c
feat: expose transaction template and helper method on the wallet
r4mmer Jan 7, 2025
61b9502
chore: linter changes
r4mmer Jan 8, 2025
ba4110d
test(integration): increase coverage on integration tests
r4mmer Jan 8, 2025
1d8cb3f
tests(integration): change position of tests
r4mmer Jan 8, 2025
b2cd834
tests(integration): change tx version
r4mmer Jan 8, 2025
d82aa19
feat: make tx signing optional when building with the facade
r4mmer Jan 9, 2025
33591c3
feat: correctly pass the arguments to build template
r4mmer Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: add support for create token transaction
  • Loading branch information
r4mmer committed Dec 16, 2024
commit a342ab7e390b3035934fa907bf9be0f7bc88dfe8
20 changes: 19 additions & 1 deletion src/template/transaction/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import Input from '../../models/input';
import Output from '../../models/output';
import transactionUtils from '../../utils/transaction';
import { DEFAULT_TX_VERSION, NATIVE_TOKEN_UID } from '../../constants';
import { CREATE_TOKEN_TX_VERSION, DEFAULT_TX_VERSION, NATIVE_TOKEN_UID } from '../../constants';

export interface TokenBalance {
tokens: OutputValueType;
Expand All @@ -22,63 +22,63 @@
balance: Record<string, TokenBalance>;

constructor() {
this.balance = {};

Check warning on line 25 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L25

Added line #L25 was not covered by tests
}

getTokenBalance(token: string): TokenBalance {
if (!this.balance[token]) {
this.balance[token] = {

Check warning on line 30 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L30

Added line #L30 was not covered by tests
tokens: 0n,
mint_authorities: 0,
melt_authorities: 0,
};
}

return this.balance[token];

Check warning on line 37 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L37

Added line #L37 was not covered by tests
}

setTokenBalance(token: string, balance: TokenBalance) {
this.balance[token] = balance;

Check warning on line 41 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L41

Added line #L41 was not covered by tests
}

addInput(tx: IHistoryTx, index: number) {
if (tx.outputs.length <= index) {
throw new Error('Index does not exist on tx outputs');

Check warning on line 46 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L46

Added line #L46 was not covered by tests
}
const output = tx.outputs[index];
const { token } = output;
const balance = this.getTokenBalance(token);

Check warning on line 50 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L48-L50

Added lines #L48 - L50 were not covered by tests

if (transactionUtils.isAuthorityOutput(output)) {
if (transactionUtils.isMint(output)) {
balance.mint_authorities += 1;

Check warning on line 54 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L54

Added line #L54 was not covered by tests
}

if (transactionUtils.isMelt(output)) {
balance.melt_authorities += 1;

Check warning on line 58 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L58

Added line #L58 was not covered by tests
}
} else {
balance.tokens += output.value;

Check warning on line 61 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L61

Added line #L61 was not covered by tests
}

this.setTokenBalance(token, balance);

Check warning on line 64 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L64

Added line #L64 was not covered by tests
}

addOutput(amount: OutputValueType, token: string) {
const balance = this.getTokenBalance(token);
balance.tokens -= amount;
this.setTokenBalance(token, balance);

Check warning on line 70 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L68-L70

Added lines #L68 - L70 were not covered by tests
}

addOutputAuthority(count: number, token: string, authority: 'mint'|'melt') {
const balance = this.getTokenBalance(token);

Check warning on line 74 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L74

Added line #L74 was not covered by tests
if (authority === 'mint') {
balance.mint_authorities -= count;

Check warning on line 76 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L76

Added line #L76 was not covered by tests
}
if (authority === 'melt') {
balance.melt_authorities -= count;

Check warning on line 79 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L79

Added line #L79 was not covered by tests
}
this.setTokenBalance(token, balance);

Check warning on line 81 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L81

Added line #L81 was not covered by tests
}
}

Expand Down Expand Up @@ -108,58 +108,76 @@
debug: boolean;

constructor(logger?: ILogger, debug: boolean = false) {
this.inputs = [];
this.outputs = [];
this.tokens = [];
this.version = DEFAULT_TX_VERSION;
this.signalBits = 0;
this.balance = new TxBalance();
this.vars = {};
this._logs = [];

Check warning on line 118 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L111-L118

Added lines #L111 - L118 were not covered by tests
this._logger = logger ?? getDefaultLogger();
this.debug = debug;

Check warning on line 120 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L120

Added line #L120 was not covered by tests
}

log(message: string): void {
this._logs.push(message);

Check warning on line 124 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L124

Added line #L124 was not covered by tests
if (this.debug) {
this._logger.info(message);

Check warning on line 126 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L126

Added line #L126 was not covered by tests
}
}

get logArray(): string[] {
return this._logs;

Check warning on line 131 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L131

Added line #L131 was not covered by tests
}

useCreateTxContext() {
if (this.tokens.length !== 0) {
throw new Error(`Trying to build a create token tx with ${this.tokens.length} tokens on the array`);

Check warning on line 136 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L136

Added line #L136 was not covered by tests
}
this.version = CREATE_TOKEN_TX_VERSION;

Check warning on line 138 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L138

Added line #L138 was not covered by tests
}

getTokenDataFor(token: string, useCreatedToken: boolean) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chore: Change the name of the method to better communicate its purpose. As of now, it is a get method that actually mutates the object and adds a new token.

Also, when useCreatedToken is passed, token is discarded, which is also slightly confusing and would be better accompanied by a method docstring to explain it.

if (useCreatedToken) {
this.useCreateTxContext();
return 1;

Check warning on line 144 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L143-L144

Added lines #L143 - L144 were not covered by tests
}
return this.addToken(token);

Check warning on line 146 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L146

Added line #L146 was not covered by tests
}

addToken(token: string) {
if (token === NATIVE_TOKEN_UID) {
return 0;

Check warning on line 151 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L151

Added line #L151 was not covered by tests
}
if (this.version === CREATE_TOKEN_TX_VERSION) {
throw new Error(`Cannot add a custom token to a CREATE_TOKEN_TX`);

Check warning on line 154 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L154

Added line #L154 was not covered by tests
}
const index = this.tokens.indexOf(token);

Check warning on line 156 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L156

Added line #L156 was not covered by tests
if (index > -1) {
// Token is already on the list.
return index + 1;

Check warning on line 159 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L159

Added line #L159 was not covered by tests
}
// Token is not on the list, adding now
this.tokens.push(token);
return this.tokens.length;

Check warning on line 163 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L162-L163

Added lines #L162 - L163 were not covered by tests
}

addInput(position: number, ...inputs: Input[]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chore: Change the name to better inform that multiple inputs can be added, and that the expected parameter is actually an array and not an object. Initial suggestions would be addInputs or addManyInputs.

if (position === -1) {
this.inputs.push(...inputs);
return;

Check warning on line 169 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L168-L169

Added lines #L168 - L169 were not covered by tests
}

this.inputs.splice(position, 0, ...inputs);

Check warning on line 172 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L172

Added line #L172 was not covered by tests
}

addOutput(position: number, ...outputs: Output[]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chore: Same plural naming issue described above.

if (position === -1) {
this.outputs.push(...outputs);
return;

Check warning on line 178 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L177-L178

Added lines #L177 - L178 were not covered by tests
}

this.outputs.splice(position, 0, ...outputs);

Check warning on line 181 in src/template/transaction/context.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/context.ts#L181

Added line #L181 was not covered by tests
}
}
61 changes: 45 additions & 16 deletions src/template/transaction/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,19 +47,19 @@
ctx: TxTemplateContext,
ins: z.infer<typeof RawInputInstruction>
) {
ctx.log(`Begin RawInputInstruction: ${JSONBigInt.stringify(ins)}`);
const position = ins.position;
const txId = getVariable<string>(ins.txId, ctx.vars, RawInputInstruction.shape.txId);
const index = getVariable<number>(ins.index, ctx.vars, RawInputInstruction.shape.index);
ctx.log(`index(${index}), txId(${txId})`);

Check warning on line 54 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L50-L54

Added lines #L50 - L54 were not covered by tests

// Find the original transaction from the input
const origTx = await interpreter.getTx(txId);

Check warning on line 57 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L57

Added line #L57 was not covered by tests
// Add balance to the ctx.balance
ctx.balance.addInput(origTx, index);

Check warning on line 59 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L59

Added line #L59 was not covered by tests

const input = new Input(txId, index);
ctx.addInput(position, input);

Check warning on line 62 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L61-L62

Added lines #L61 - L62 were not covered by tests
}

/**
Expand All @@ -70,54 +70,54 @@
ctx: TxTemplateContext,
ins: z.infer<typeof UtxoSelectInstruction>
) {
ctx.log(`Begin UtxoSelectInstruction: ${JSONBigInt.stringify(ins)}`);
const position = ins.position;
const fill = getVariable<bigint>(ins.fill, ctx.vars, UtxoSelectInstruction.shape.fill);
const token = getVariable<string>(ins.token, ctx.vars, UtxoSelectInstruction.shape.token);
const address = getVariable<string|undefined>(ins.address, ctx.vars, UtxoSelectInstruction.shape.address);
ctx.log(`fill(${fill}), address(${address}), token(${token})`);

Check warning on line 78 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L73-L78

Added lines #L73 - L78 were not covered by tests

const autoChange = ins.autoChange;

Check warning on line 80 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L80

Added line #L80 was not covered by tests

// Find utxos
const options: IGetUtxosOptions = { token };

Check warning on line 83 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L83

Added line #L83 was not covered by tests
if (address) {
options.filter_address = address;

Check warning on line 85 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L85

Added line #L85 was not covered by tests
}
const { changeAmount, utxos } = await interpreter.getUtxos(fill, options);

Check warning on line 87 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L87

Added line #L87 was not covered by tests

// Add utxos as inputs on the transaction
const inputs: Input[] = [];
for (const utxo of utxos) {
ctx.log(`Found utxo with ${utxo.value} of ${utxo.tokenId}`);
ctx.log(`Create input ${utxo.index} / ${utxo.txId}`);
inputs.push(new Input(utxo.txId, utxo.index));

Check warning on line 94 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L90-L94

Added lines #L90 - L94 were not covered by tests
}

// First, update balance
for (const input of inputs) {
const origTx = await interpreter.getTx(input.hash);
ctx.balance.addInput(origTx, input.index);

Check warning on line 100 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L98-L100

Added lines #L98 - L100 were not covered by tests
}

// Then add inputs to context
ctx.addInput(position, ...inputs);

Check warning on line 104 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L104

Added line #L104 was not covered by tests

ctx.log(`changeAmount: ${changeAmount}`);

Check warning on line 106 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L106

Added line #L106 was not covered by tests

if (autoChange && changeAmount) {
// get change address
let changeAddress = getVariable<string|undefined>(ins.changeAddress, ctx.vars, UtxoSelectInstruction.shape.changeAddress);

Check warning on line 110 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L110

Added line #L110 was not covered by tests
if (!changeAddress) {
changeAddress = await interpreter.getChangeAddress(ctx);

Check warning on line 112 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L112

Added line #L112 was not covered by tests
}
ctx.log(`Creating change for address: ${changeAddress}`);

Check warning on line 114 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L114

Added line #L114 was not covered by tests
// Token should only be on the array if present on the outputs
const tokenData = ctx.addToken(token);
const script = createOutputScriptFromAddress(changeAddress, interpreter.getNetwork());
const output = new Output(changeAmount, script, { tokenData });
ctx.balance.addOutput(changeAmount, token);
ctx.addOutput(-1, output);

Check warning on line 120 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L116-L120

Added lines #L116 - L120 were not covered by tests
}
}

Expand All @@ -129,47 +129,47 @@
ctx: TxTemplateContext,
ins: z.infer<typeof AuthoritySelectInstruction>
) {
ctx.log(`Begin AuthoritySelectInstruction: ${JSONBigInt.stringify(ins)}`);

Check warning on line 132 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L132

Added line #L132 was not covered by tests
const position = ins.position ?? -1;
const authority = ins.authority;
const token = getVariable<string>(ins.token, ctx.vars, AuthoritySelectInstruction.shape.token);
const count = getVariable<number>(ins.count, ctx.vars,AuthoritySelectInstruction.shape.count);
const address = getVariable<string|undefined>(ins.address, ctx.vars,AuthoritySelectInstruction.shape.address);
ctx.log(`count(${count}), address(${address}), token(${token})`);

Check warning on line 138 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L134-L138

Added lines #L134 - L138 were not covered by tests

let authoritiesInt = 0n;

Check warning on line 140 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L140

Added line #L140 was not covered by tests
if (authority === 'mint') {
authoritiesInt += 1n;

Check warning on line 142 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L142

Added line #L142 was not covered by tests
}
if (authority === 'melt') {
authoritiesInt += 2n;

Check warning on line 145 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L145

Added line #L145 was not covered by tests
}

// Find utxos
const options: IGetUtxosOptions = {

Check warning on line 149 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L149

Added line #L149 was not covered by tests
token,
authorities: authoritiesInt,
};
if (address) {
options.filter_address = address;

Check warning on line 154 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L154

Added line #L154 was not covered by tests
}
const utxos = await interpreter.getAuthorities(count, options);

Check warning on line 156 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L156

Added line #L156 was not covered by tests

// Add utxos as inputs on the transaction
const inputs: Input[] = [];
for (const utxo of utxos) {
ctx.log(`Found authority utxo ${utxo.authorities} of ${token}`);
ctx.log(`Create input ${utxo.index} / ${utxo.txId}`);
inputs.push(new Input(utxo.txId, utxo.index));

Check warning on line 163 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L159-L163

Added lines #L159 - L163 were not covered by tests
}
// First, update balance
for (const input of inputs) {
const origTx = await interpreter.getTx(input.hash);
ctx.balance.addInput(origTx, input.index);

Check warning on line 168 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L166-L168

Added lines #L166 - L168 were not covered by tests
}

// Then add inputs to context
ctx.addInput(position, ...inputs);

Check warning on line 172 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L172

Added line #L172 was not covered by tests
}

/**
Expand All @@ -180,49 +180,54 @@
ctx: TxTemplateContext,
ins: z.infer<typeof RawOutputInstruction>
) {
ctx.log(`Begin RawOutputInstruction: ${JSONBigInt.stringify(ins)}`);
const { position, authority } = ins;
const { position, authority, useCreatedToken } = ins;
const scriptStr = getVariable<string>(ins.script, ctx.vars,RawOutputInstruction.shape.script);
const script = Buffer.from(scriptStr, 'hex');
const token = getVariable<string>(ins.token, ctx.vars,RawOutputInstruction.shape.token);
const timelock = getVariable<number|undefined>(ins.timelock, ctx.vars, RawOutputInstruction.shape.timelock);

Check warning on line 188 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L183-L188

Added lines #L183 - L188 were not covered by tests

// Add token to tokens array
const tokenIndex = ctx.addToken(token);
let tokenData = tokenIndex;
let tokenData: number;
if (useCreatedToken) {
ctx.useCreateTxContext()
tokenData = 1;

Check warning on line 193 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L192-L193

Added lines #L192 - L193 were not covered by tests
} else {
// Add token to tokens array
tokenData = ctx.addToken(token);

Check warning on line 196 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L196

Added line #L196 was not covered by tests
}

let amount: OutputValueType|undefined = 0n;

Check warning on line 199 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L199

Added line #L199 was not covered by tests
switch (authority) {
case 'mint':
amount = TOKEN_MINT_MASK;
tokenData |= TOKEN_AUTHORITY_MASK;
break;

Check warning on line 204 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L202-L204

Added lines #L202 - L204 were not covered by tests
case 'melt':
amount = TOKEN_MELT_MASK;
tokenData |= TOKEN_AUTHORITY_MASK;
break;

Check warning on line 208 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L206-L208

Added lines #L206 - L208 were not covered by tests
default: {
amount = getVariable<bigint|undefined>(ins.amount, ctx.vars,RawOutputInstruction.shape.amount);
break;

Check warning on line 211 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L210-L211

Added lines #L210 - L211 were not covered by tests
}

}
ctx.log(`amount(${amount}) timelock(${timelock}) script(${script}) token(${token})`);

Check warning on line 215 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L215

Added line #L215 was not covered by tests
if (!amount) {
throw new Error('Raw token output missing amount');

Check warning on line 217 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L217

Added line #L217 was not covered by tests
}

// Add balance to the ctx.balance
if (authority) {
ctx.log(`Creating authority output`);
ctx.balance.addOutputAuthority(1, token, authority);

Check warning on line 223 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L222-L223

Added lines #L222 - L223 were not covered by tests
} else {
ctx.log(`Creating token output`);
ctx.balance.addOutput(amount, token);

Check warning on line 226 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L225-L226

Added lines #L225 - L226 were not covered by tests
}

const output = new Output(amount, script, { timelock, tokenData });
ctx.addOutput(position, output);

Check warning on line 230 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L229-L230

Added lines #L229 - L230 were not covered by tests
}

/**
Expand All @@ -233,22 +238,30 @@
ctx: TxTemplateContext,
ins: z.infer<typeof DataOutputInstruction>
) {
ctx.log(`Begin DataOutputInstruction: ${JSONBigInt.stringify(ins)}`);
const position = ins.position;
const { position, useCreatedToken } = ins;
const data = getVariable<string>(ins.data, ctx.vars,DataOutputInstruction.shape.data);
const token = getVariable<string>(ins.token, ctx.vars,DataOutputInstruction.shape.token);
ctx.log(`Creating data(${data}) output of token(${token})`);
ctx.log(`Creating data(${data}) output`);

Check warning on line 245 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L241-L245

Added lines #L241 - L245 were not covered by tests

// Add token to tokens array
const tokenData = ctx.addToken(token);
let tokenData: number;
if (useCreatedToken) {
ctx.log(`Using created token`);
ctx.useCreateTxContext()
tokenData = 1;

Check warning on line 251 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L249-L251

Added lines #L249 - L251 were not covered by tests
} else {
ctx.log(`Using token(${token})`);

Check warning on line 253 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L253

Added line #L253 was not covered by tests
// Add token to tokens array
tokenData = ctx.addToken(token);

Check warning on line 255 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L255

Added line #L255 was not covered by tests
}

// Add balance to the ctx.balance
ctx.balance.addOutput(1n, token);

Check warning on line 259 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L259

Added line #L259 was not covered by tests

const dataScript = new ScriptData(data);
const script = dataScript.createScript();
const output = new Output(1n, script, { tokenData });
ctx.addOutput(position, output);

Check warning on line 264 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L261-L264

Added lines #L261 - L264 were not covered by tests
}

/**
Expand All @@ -259,23 +272,31 @@
ctx: TxTemplateContext,
ins: z.infer<typeof TokenOutputInstruction>
) {
ctx.log(`Begin TokenOutputInstruction: ${JSONBigInt.stringify(ins)}`);
const position = ins.position;
const { position, useCreatedToken } = ins;
const token = getVariable<string>(ins.token, ctx.vars,TokenOutputInstruction.shape.token);
const address = getVariable<string>(ins.address, ctx.vars,TokenOutputInstruction.shape.address);
const timelock = getVariable<number|undefined>(ins.timelock, ctx.vars, TokenOutputInstruction.shape.timelock);
const amount = getVariable<bigint>(ins.amount, ctx.vars, TokenOutputInstruction.shape.amount);
ctx.log(`Creating token output with amount(${amount}) address(${address}) timelock(${timelock}) token(${token})`);
ctx.log(`Creating token output with amount(${amount}) address(${address}) timelock(${timelock})`);

Check warning on line 281 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L275-L281

Added lines #L275 - L281 were not covered by tests

// Add token to tokens array
const tokenData = ctx.addToken(token);
let tokenData: number;
if (useCreatedToken) {
ctx.log(`Using created token`);
ctx.useCreateTxContext()
tokenData = 1;

Check warning on line 287 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L285-L287

Added lines #L285 - L287 were not covered by tests
} else {
ctx.log(`Using token(${token})`);

Check warning on line 289 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L289

Added line #L289 was not covered by tests
// Add token to tokens array
tokenData = ctx.addToken(token);

Check warning on line 291 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L291

Added line #L291 was not covered by tests
}

// Add balance to the ctx.balance
ctx.balance.addOutput(amount, token);

Check warning on line 295 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L295

Added line #L295 was not covered by tests

const script = createOutputScriptFromAddress(address, interpreter.getNetwork());
const output = new Output(amount, script, { timelock, tokenData });
ctx.addOutput(position, output);

Check warning on line 299 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L297-L299

Added lines #L297 - L299 were not covered by tests
}

/**
Expand All @@ -286,38 +307,46 @@
ctx: TxTemplateContext,
ins: z.infer<typeof AuthorityOutputInstruction>
) {
ctx.log(`Begin AuthorityOutputInstruction: ${JSONBigInt.stringify(ins)}`);
const { authority, position } = ins;
const { authority, position, useCreatedToken } = ins;
const token = getVariable<string>(ins.token, ctx.vars, AuthorityOutputInstruction.shape.token);
const address = getVariable<string>(ins.address, ctx.vars,AuthorityOutputInstruction.shape.address);
const timelock = getVariable<number|undefined>(ins.timelock, ctx.vars, AuthorityOutputInstruction.shape.timelock);
const count = getVariable<number>(ins.count, ctx.vars, AuthorityOutputInstruction.shape.count);
ctx.log(`Creating count(${count}) ${authority} authority outputs with address(${address}) timelock(${timelock}) token(${token})`);
ctx.log(`Creating count(${count}) "${authority}" authority outputs with address(${address}) timelock(${timelock})`);

Check warning on line 316 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L310-L316

Added lines #L310 - L316 were not covered by tests

// Add token to tokens array
let tokenData = ctx.addToken(token);
let tokenData: number;
if (useCreatedToken) {
ctx.log(`Using created token`);
ctx.useCreateTxContext()
tokenData = 1;

Check warning on line 322 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L320-L322

Added lines #L320 - L322 were not covered by tests
} else {
ctx.log(`Using token(${token})`);

Check warning on line 324 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L324

Added line #L324 was not covered by tests
// Add token to tokens array
tokenData = ctx.addToken(token);

Check warning on line 326 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L326

Added line #L326 was not covered by tests
}

let amount: OutputValueType|undefined = 0n;

Check warning on line 329 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L329

Added line #L329 was not covered by tests
switch(authority) {
case 'mint':
amount = TOKEN_MINT_MASK;
tokenData |= TOKEN_AUTHORITY_MASK;
break;

Check warning on line 334 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L332-L334

Added lines #L332 - L334 were not covered by tests
case 'melt':
amount = TOKEN_MELT_MASK;
tokenData |= TOKEN_AUTHORITY_MASK;
break;

Check warning on line 338 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L336-L338

Added lines #L336 - L338 were not covered by tests
default:
throw new Error('Authority token output missing `authority`');

Check warning on line 340 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L340

Added line #L340 was not covered by tests
}

// Add balance to the ctx.balance
ctx.balance.addOutputAuthority(count, token, authority);

Check warning on line 344 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L344

Added line #L344 was not covered by tests

const script = createOutputScriptFromAddress(address, interpreter.getNetwork());
const output = new Output(amount, script, { timelock, tokenData });

Check warning on line 347 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L346-L347

Added lines #L346 - L347 were not covered by tests
// Creates `count` outputs that are copies of the `output`
ctx.addOutput(position, ...Array(count).fill(output));

Check warning on line 349 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L349

Added line #L349 was not covered by tests
}

/**
Expand All @@ -328,18 +357,18 @@
ctx: TxTemplateContext,
ins: z.infer<typeof ShuffleInstruction>
) {
ctx.log(`Begin ShuffleInstruction: ${JSONBigInt.stringify(ins)}`);
const { target } = ins;

Check warning on line 361 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L360-L361

Added lines #L360 - L361 were not covered by tests

// The token array should never be shuffled since outputs have a "pointer" to the token position
// on the token array, so shuffling would make the outputs target different outputs.

if (target === 'inputs' || target === 'all') {
ctx.inputs = shuffle(ctx.inputs);

Check warning on line 367 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L367

Added line #L367 was not covered by tests
}

if (target === 'outputs' || target === 'all') {
ctx.outputs = shuffle(ctx.outputs);

Check warning on line 371 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L371

Added line #L371 was not covered by tests
}
}

Expand All @@ -351,56 +380,56 @@
ctx: TxTemplateContext,
ins: z.infer<typeof ChangeInstruction>
) {
ctx.log(`Begin ChangeInstruction: ${JSONBigInt.stringify(ins)}`);
const token = getVariable<string|undefined>(ins.token, ctx.vars,ChangeInstruction.shape.token);

Check warning on line 384 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L383-L384

Added lines #L383 - L384 were not covered by tests
const address = getVariable<string|undefined>(ins.address, ctx.vars,ChangeInstruction.shape.address) ?? await interpreter.getChangeAddress(ctx);
const timelock = getVariable<number|undefined>(ins.timelock, ctx.vars, ChangeInstruction.shape.timelock);
ctx.log(`address(${address}) timelock(${timelock}) token(${token})`);

Check warning on line 387 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L386-L387

Added lines #L386 - L387 were not covered by tests

const tokensToCheck: string[] = [];

Check warning on line 389 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L389

Added line #L389 was not covered by tests
if (token) {
tokensToCheck.push(token);

Check warning on line 391 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L391

Added line #L391 was not covered by tests
} else {
// Check HTR and all tokens on the transaction
tokensToCheck.push(NATIVE_TOKEN_UID);
for (const tk in ctx.tokens) {
tokensToCheck.push(tk);

Check warning on line 396 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L394-L396

Added lines #L394 - L396 were not covered by tests
}
}

const script = createOutputScriptFromAddress(address, interpreter.getNetwork());

Check warning on line 400 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L400

Added line #L400 was not covered by tests

for (const tokenUid of tokensToCheck) {
const balance = ctx.balance.getTokenBalance(tokenUid);
const tokenData = ctx.addToken(tokenUid);

Check warning on line 404 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L402-L404

Added lines #L402 - L404 were not covered by tests
if (balance.tokens > 0) {
// Need to create a token output
// Add balance to the ctx.balance
ctx.balance.addOutput(balance.tokens, tokenUid);

Check warning on line 408 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L408

Added line #L408 was not covered by tests

// Creates an output with the value of the outstanding balance
const output = new Output(balance.tokens, script, { timelock, tokenData });
ctx.addOutput(-1, output);

Check warning on line 412 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L411-L412

Added lines #L411 - L412 were not covered by tests
}

if (balance.mint_authorities > 0) {
// Need to create a token output
// Add balance to the ctx.balance
ctx.balance.addOutputAuthority(balance.mint_authorities, tokenUid, 'mint');

Check warning on line 418 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L418

Added line #L418 was not covered by tests

// Creates an output with the value of the outstanding balance
const output = new Output(TOKEN_MINT_MASK, script, { timelock, tokenData });
ctx.addOutput(-1, ...Array(balance.mint_authorities).fill(output));

Check warning on line 422 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L421-L422

Added lines #L421 - L422 were not covered by tests
}

if (balance.melt_authorities > 0) {
// Need to create a token output
// Add balance to the ctx.balance
ctx.balance.addOutputAuthority(balance.melt_authorities, tokenUid, 'melt');

Check warning on line 428 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L428

Added line #L428 was not covered by tests

// Creates an output with the value of the outstanding balance
const output = new Output(TOKEN_MELT_MASK, script, { timelock, tokenData });
ctx.addOutput(-1, ...Array(balance.melt_authorities).fill(output));

Check warning on line 432 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L431-L432

Added lines #L431 - L432 were not covered by tests
}
}
}
Expand All @@ -413,24 +442,24 @@
ctx: TxTemplateContext,
ins: z.infer<typeof ConfigInstruction>
) {
ctx.log(`Begin ConfigInstruction: ${JSONBigInt.stringify(ins)}`);
const version = getVariable<number|undefined>(ins.version, ctx.vars, ConfigInstruction.shape.version);
const signalBits = getVariable<number|undefined>(ins.signalBits, ctx.vars, ConfigInstruction.shape.signalBits);
const tokenName = getVariable<string|undefined>(ins.tokenName, ctx.vars, ConfigInstruction.shape.tokenName);
const tokenSymbol = getVariable<string|undefined>(ins.tokenSymbol, ctx.vars, ConfigInstruction.shape.tokenSymbol);
ctx.log(`version(${version}) signalBits(${signalBits}) tokenName(${tokenName}) tokenSymbol(${tokenSymbol})`);

Check warning on line 450 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L445-L450

Added lines #L445 - L450 were not covered by tests

if (version) {
ctx.version = version;

Check warning on line 453 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L453

Added line #L453 was not covered by tests
}
if (signalBits) {
ctx.signalBits = signalBits;

Check warning on line 456 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L456

Added line #L456 was not covered by tests
}
if (tokenName) {
ctx.tokenName = tokenName;

Check warning on line 459 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L459

Added line #L459 was not covered by tests
}
if (tokenSymbol) {
ctx.tokenSymbol = tokenSymbol;

Check warning on line 462 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L462

Added line #L462 was not covered by tests
}
}

Expand All @@ -442,34 +471,34 @@
ctx: TxTemplateContext,
ins: z.infer<typeof SetVarInstruction>
) {
ctx.log(`Begin SetVarInstruction: ${JSONBigInt.stringify(ins)}`);

Check warning on line 474 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L474

Added line #L474 was not covered by tests
if (!ins.action) {
ctx.log(`Setting ${ins.name} with ${ins.value}`);
ctx.vars[ins.name] = ins.value;
return;

Check warning on line 478 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L476-L478

Added lines #L476 - L478 were not covered by tests
}

if (ins.action === 'get_wallet_address') {
// Validate options and get token variable
const options = SetVarGetWalletAddressOpts.default({}).parse(ins.options);
const token = getVariable<string>(options.token, ctx.vars, SetVarGetWalletAddressOpts.shape.token);
options.token = token;

Check warning on line 485 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L483-L485

Added lines #L483 - L485 were not covered by tests
// Call action with valid options
const address = await getWalletAddress(interpreter, ctx, options);
ctx.log(`Setting ${ins.name} with ${address}`);
ctx.vars[ins.name] = address;
return;

Check warning on line 490 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L487-L490

Added lines #L487 - L490 were not covered by tests
}
if (ins.action === 'get_wallet_balance') {
// Validate options and get token variable
const options = SetVarGetWalletBalanceOpts.default({}).parse(ins.options);
const token = getVariable<string>(options.token, ctx.vars, SetVarGetWalletBalanceOpts.shape.token);
options.token = token;

Check warning on line 496 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L494-L496

Added lines #L494 - L496 were not covered by tests
// Call action with valid options
const balance = await getWalletBalance(interpreter, ctx, options);
ctx.vars[ins.name] = balance;
ctx.log(`Setting ${ins.name} with ${balance}`);
return;

Check warning on line 501 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L498-L501

Added lines #L498 - L501 were not covered by tests
}
throw new Error('Invalid setvar command');

Check warning on line 503 in src/template/transaction/executor.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/executor.ts#L503

Added line #L503 was not covered by tests
}
4 changes: 4 additions & 0 deletions src/template/transaction/instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import { NATIVE_TOKEN_UID } from '../../constants';
import { z } from 'zod';

const TEMPLATE_REFERENCE_RE = /\{([\w\d]+)\}/;
export const TemplateRef = z.string().regex(TEMPLATE_REFERENCE_RE);

Check warning on line 12 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L11-L12

Added lines #L11 - L12 were not covered by tests

/**
* If the key matches a template reference (i.e. `{name}`) it returns the variable of that name.
Expand Down Expand Up @@ -40,42 +40,42 @@
vars: Record<string, unknown>,
schema: T,
): S {
let val = ref; // type should be: string | S
const parsed = TemplateRef.safeParse(ref);

Check warning on line 44 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L43-L44

Added lines #L43 - L44 were not covered by tests
if (parsed.success) {
const match = parsed.data.match(TEMPLATE_REFERENCE_RE);

Check warning on line 46 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L46

Added line #L46 was not covered by tests
if (match !== null) {
const key = match[1];

Check warning on line 48 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L48

Added line #L48 was not covered by tests
if (!vars[key]) {
throw new Error(`Variable ${key} not found in available variables`);

Check warning on line 50 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L50

Added line #L50 was not covered by tests
}
// We assume that the variable in the context is of type S and we validate this.
// The case where a `{...}` string is saved is not possible since we do not
// allow this type of string as variable.
val = vars[key] as S;

Check warning on line 55 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L55

Added line #L55 was not covered by tests
}
}

return schema.parse(val) as S;

Check warning on line 59 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L59

Added line #L59 was not covered by tests
}

// Transaction IDs and Custom Tokens are sha256 hex encoded
export const Sha256HexSchema = z.string().regex(/^[a-fA-F0-9]{64}$/);
export const TxIdSchema = Sha256HexSchema;
export const CustomTokenSchema = Sha256HexSchema;

Check warning on line 65 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L63-L65

Added lines #L63 - L65 were not covered by tests
// If we want to represent all tokens we need to include the native token uid 00
export const TokenSchema = z.string().regex(/^[a-fA-F0-9]{64}|00$/);

Check warning on line 67 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L67

Added line #L67 was not covered by tests
// Addresses are base58 with length 34, may be 35 depending on the choice of version byte
export const AddressSchema = z.string().regex(/^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{34,35}$/);

Check warning on line 69 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L69

Added line #L69 was not covered by tests

export const RawInputInstruction = z.object({

Check warning on line 71 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L71

Added line #L71 was not covered by tests
type: z.literal('input/raw'),
position: z.number().default(-1),
index: TemplateRef.or(z.coerce.number()),
txId: TemplateRef.or(TxIdSchema),
});

export const UtxoSelectInstruction = z.object({

Check warning on line 78 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L78

Added line #L78 was not covered by tests
type: z.literal('input/utxo'),
position: z.number().default(-1),
fill: TemplateRef.or(z.coerce.bigint()),
Expand All @@ -85,7 +85,7 @@
changeAddress: TemplateRef.or(AddressSchema.optional()),
});

export const AuthoritySelectInstruction = z.object({

Check warning on line 88 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L88

Added line #L88 was not covered by tests
type: z.literal('input/authority'),
position: z.number().default(-1),
authority: z.enum(['mint', 'melt']),
Expand All @@ -94,7 +94,7 @@
address: TemplateRef.or(AddressSchema.optional()),
});

export const RawOutputInstruction = z.object({

Check warning on line 97 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L97

Added line #L97 was not covered by tests
type: z.literal('output/raw'),
position: z.number().default(-1),
amount: TemplateRef.or(z.coerce.bigint().optional()),
Expand All @@ -102,9 +102,10 @@
token: TemplateRef.or(TokenSchema.default('00')),
timelock: TemplateRef.or(z.coerce.number().optional()),
authority: z.enum(['mint', 'melt']).optional(),
useCreatedToken: z.boolean().default(false),
});

export const TokenOutputInstruction = z.object({

Check warning on line 108 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L108

Added line #L108 was not covered by tests
type: z.literal('output/token'),
position: z.number().default(-1),
amount: TemplateRef.or(z.coerce.bigint()),
Expand All @@ -112,9 +113,10 @@
address: TemplateRef.or(AddressSchema),
timelock: TemplateRef.or(z.coerce.number().optional()),
checkAddress: z.boolean().optional(),
useCreatedToken: z.boolean().default(false),
});

export const AuthorityOutputInstruction = z.object({

Check warning on line 119 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L119

Added line #L119 was not covered by tests
type: z.literal('output/authority'),
position: z.number().default(-1),
count: TemplateRef.or(z.coerce.number().default(1)),
Expand All @@ -123,28 +125,30 @@
address: TemplateRef.or(AddressSchema),
timelock: TemplateRef.or(z.coerce.number().optional()),
checkAddress: z.boolean().optional(),
useCreatedToken: z.boolean().default(false),
});

export const DataOutputInstruction = z.object({

Check warning on line 131 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L131

Added line #L131 was not covered by tests
type: z.literal('output/data'),
position: z.number().default(-1),
data: TemplateRef.or(z.string()),
token: TemplateRef.or(TokenSchema.default(NATIVE_TOKEN_UID)),
useCreatedToken: z.boolean().default(false),
});

export const ShuffleInstruction = z.object({

Check warning on line 139 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L139

Added line #L139 was not covered by tests
type: z.literal('action/shuffle'),
target: z.enum(['inputs', 'outputs', 'all']),
});

export const ChangeInstruction = z.object({

Check warning on line 144 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L144

Added line #L144 was not covered by tests
type: z.literal('action/change'),
token: TemplateRef.or(TokenSchema.optional()),
address: TemplateRef.or(AddressSchema.optional()),
timelock: TemplateRef.or(z.coerce.number().optional()),
});

export const CompleteTxInstruction = z.object({

Check warning on line 151 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L151

Added line #L151 was not covered by tests
type: z.literal('action/complete'),
token: TemplateRef.or(TokenSchema.optional()),
address: TemplateRef.or(z.string().optional()),
Expand All @@ -152,7 +156,7 @@
timelock: TemplateRef.or(z.coerce.number()).optional(),
});

export const ConfigInstruction = z.object({

Check warning on line 159 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L159

Added line #L159 was not covered by tests
type: z.literal('action/config'),
version: TemplateRef.or(z.number().optional()),
signalBits: TemplateRef.or(z.number().optional()),
Expand All @@ -160,20 +164,20 @@
tokenSymbol: TemplateRef.or(z.string().optional()),
});

export const SetVarGetWalletAddressOpts = z.object({

Check warning on line 167 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L167

Added line #L167 was not covered by tests
unused: z.boolean().optional(),
withBalance: z.number().optional(),
authority: z.enum(['mint', 'melt']).optional(),
token: TemplateRef.or(TokenSchema.default(NATIVE_TOKEN_UID)),
});

export const SetVarGetWalletBalanceOpts = z.object({

Check warning on line 174 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L174

Added line #L174 was not covered by tests
token: TemplateRef.or(TokenSchema.default('00')),
});

export const SetVarOptions = z.union([SetVarGetWalletAddressOpts, SetVarGetWalletBalanceOpts]);

Check warning on line 178 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L178

Added line #L178 was not covered by tests

export const SetVarInstruction = z.object({

Check warning on line 180 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L180

Added line #L180 was not covered by tests
type: z.literal('action/setvar'),
name: z.string().regex(/[\d\w]+/),
value: z.any().optional(),
Expand All @@ -181,7 +185,7 @@
options: SetVarOptions.optional(),
});

export const TxTemplateInstruction = z.discriminatedUnion('type', [

Check warning on line 188 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L188

Added line #L188 was not covered by tests
RawInputInstruction,
UtxoSelectInstruction,
AuthoritySelectInstruction,
Expand All @@ -197,5 +201,5 @@
]);
export type TxTemplateInstructionType = z.infer<typeof TxTemplateInstruction>;

export const TransactionTemplate = z.array(TxTemplateInstruction);

Check warning on line 204 in src/template/transaction/instructions.ts

View check run for this annotation

Codecov / codecov/patch

src/template/transaction/instructions.ts#L204

Added line #L204 was not covered by tests
export type TransactionTemplateType = z.infer<typeof TransactionTemplate>;
Loading