@centrifuge/sdk 1.10.0 → 1.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Centrifuge.d.ts +38 -0
- package/dist/Centrifuge.d.ts.map +1 -1
- package/dist/Centrifuge.js +163 -0
- package/dist/Centrifuge.js.map +1 -1
- package/dist/Centrifuge.test.js +219 -0
- package/dist/Centrifuge.test.js.map +1 -1
- package/dist/abi/MultiAdapter.abi.d.ts +1 -1
- package/dist/abi/MultiAdapter.abi.js +1 -1
- package/dist/abi/MultiAdapter.abi.js.map +1 -1
- package/dist/abi/OnchainPM.abi.d.ts +3 -0
- package/dist/abi/OnchainPM.abi.d.ts.map +1 -0
- package/dist/abi/OnchainPM.abi.js +14 -0
- package/dist/abi/OnchainPM.abi.js.map +1 -0
- package/dist/abi/OnchainPMFactory.abi.d.ts +3 -0
- package/dist/abi/OnchainPMFactory.abi.d.ts.map +1 -0
- package/dist/abi/OnchainPMFactory.abi.js +6 -0
- package/dist/abi/OnchainPMFactory.abi.js.map +1 -0
- package/dist/abi/OracleValuation.abi.d.ts +3 -0
- package/dist/abi/OracleValuation.abi.d.ts.map +1 -0
- package/dist/abi/OracleValuation.abi.js +9 -0
- package/dist/abi/OracleValuation.abi.js.map +1 -0
- package/dist/abi/ScriptHelpers.abi.d.ts +3 -0
- package/dist/abi/ScriptHelpers.abi.d.ts.map +1 -0
- package/dist/abi/ScriptHelpers.abi.js +5 -0
- package/dist/abi/ScriptHelpers.abi.js.map +1 -0
- package/dist/abi/index.d.ts +281 -0
- package/dist/abi/index.d.ts.map +1 -1
- package/dist/abi/index.js +8 -0
- package/dist/abi/index.js.map +1 -1
- package/dist/entities/OnchainPM.d.ts +203 -0
- package/dist/entities/OnchainPM.d.ts.map +1 -0
- package/dist/entities/OnchainPM.js +315 -0
- package/dist/entities/OnchainPM.js.map +1 -0
- package/dist/entities/OnchainPM.test.d.ts +2 -0
- package/dist/entities/OnchainPM.test.d.ts.map +1 -0
- package/dist/entities/OnchainPM.test.js +155 -0
- package/dist/entities/OnchainPM.test.js.map +1 -0
- package/dist/entities/Pool.d.ts +81 -3
- package/dist/entities/Pool.d.ts.map +1 -1
- package/dist/entities/Pool.js +207 -18
- package/dist/entities/Pool.js.map +1 -1
- package/dist/entities/PoolNetwork.d.ts +37 -0
- package/dist/entities/PoolNetwork.d.ts.map +1 -1
- package/dist/entities/PoolNetwork.js +136 -12
- package/dist/entities/PoolNetwork.js.map +1 -1
- package/dist/entities/PoolNetwork.test.js +134 -1
- package/dist/entities/PoolNetwork.test.js.map +1 -1
- package/dist/entities/ShareClass.d.ts.map +1 -1
- package/dist/entities/ShareClass.js +151 -126
- package/dist/entities/ShareClass.js.map +1 -1
- package/dist/entities/Vault.test.js +0 -5
- package/dist/entities/Vault.test.js.map +1 -1
- package/dist/entities/crosschainMessages.d.ts +127 -0
- package/dist/entities/crosschainMessages.d.ts.map +1 -0
- package/dist/entities/crosschainMessages.js +204 -0
- package/dist/entities/crosschainMessages.js.map +1 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/poolMetadata.d.ts +28 -0
- package/dist/types/poolMetadata.d.ts.map +1 -1
- package/dist/types/transaction.d.ts +5 -1
- package/dist/types/transaction.d.ts.map +1 -1
- package/dist/types/transaction.js.map +1 -1
- package/dist/types/workflow.d.ts +151 -0
- package/dist/types/workflow.d.ts.map +1 -0
- package/dist/types/workflow.js +5 -0
- package/dist/types/workflow.js.map +1 -0
- package/dist/utils/catalog.d.ts +29 -0
- package/dist/utils/catalog.d.ts.map +1 -0
- package/dist/utils/catalog.js +396 -0
- package/dist/utils/catalog.js.map +1 -0
- package/dist/utils/catalog.test.d.ts +2 -0
- package/dist/utils/catalog.test.d.ts.map +1 -0
- package/dist/utils/catalog.test.js +291 -0
- package/dist/utils/catalog.test.js.map +1 -0
- package/dist/utils/scriptHash.d.ts +32 -0
- package/dist/utils/scriptHash.d.ts.map +1 -0
- package/dist/utils/scriptHash.js +67 -0
- package/dist/utils/scriptHash.js.map +1 -0
- package/dist/utils/scriptHash.test.d.ts +2 -0
- package/dist/utils/scriptHash.test.d.ts.map +1 -0
- package/dist/utils/scriptHash.test.js +97 -0
- package/dist/utils/scriptHash.test.js.map +1 -0
- package/dist/utils/variables.d.ts +78 -0
- package/dist/utils/variables.d.ts.map +1 -0
- package/dist/utils/variables.js +105 -0
- package/dist/utils/variables.js.map +1 -0
- package/dist/utils/variables.test.d.ts +2 -0
- package/dist/utils/variables.test.d.ts.map +1 -0
- package/dist/utils/variables.test.js +110 -0
- package/dist/utils/variables.test.js.map +1 -0
- package/dist/utils/weiroll.d.ts +176 -0
- package/dist/utils/weiroll.d.ts.map +1 -0
- package/dist/utils/weiroll.js +341 -0
- package/dist/utils/weiroll.js.map +1 -0
- package/dist/utils/weiroll.test.d.ts +2 -0
- package/dist/utils/weiroll.test.d.ts.map +1 -0
- package/dist/utils/weiroll.test.js +430 -0
- package/dist/utils/weiroll.test.js.map +1 -0
- package/dist/utils/workflowExecute.d.ts +121 -0
- package/dist/utils/workflowExecute.d.ts.map +1 -0
- package/dist/utils/workflowExecute.js +577 -0
- package/dist/utils/workflowExecute.js.map +1 -0
- package/dist/utils/workflowExecute.test.d.ts +2 -0
- package/dist/utils/workflowExecute.test.d.ts.map +1 -0
- package/dist/utils/workflowExecute.test.js +117 -0
- package/dist/utils/workflowExecute.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { decodeAbiParameters, toFunctionSelector } from 'viem';
|
|
3
|
+
import { buildWorkflowDefinitionFromCatalog } from './catalog.js';
|
|
4
|
+
import { buildScript } from './weiroll.js';
|
|
5
|
+
const ADDRESS_A = '0x1111111111111111111111111111111111111111';
|
|
6
|
+
const ADDRESS_B = '0x2222222222222222222222222222222222222222';
|
|
7
|
+
const ADDRESS_C = '0x3333333333333333333333333333333333333333';
|
|
8
|
+
const ADDRESS_D = '0x4444444444444444444444444444444444444444';
|
|
9
|
+
const ONCHAIN_PM_BYTES32 = '0x000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
|
|
10
|
+
// Build a MarketplaceWorkflow in the tagged (explicit-input-kinds) format: the template's
|
|
11
|
+
// `variables` declare each variable's kind, and the workflow carries the template registry so
|
|
12
|
+
// the builder can read those kinds.
|
|
13
|
+
function tagged(template, variables, actions, workflowVariables) {
|
|
14
|
+
const templates = { [template]: { actions, variables } };
|
|
15
|
+
return {
|
|
16
|
+
workflowRef: template,
|
|
17
|
+
name: template,
|
|
18
|
+
template,
|
|
19
|
+
chainId: 1,
|
|
20
|
+
variables: workflowVariables,
|
|
21
|
+
workflowId: '0x01',
|
|
22
|
+
version: 1,
|
|
23
|
+
templates,
|
|
24
|
+
actions,
|
|
25
|
+
runtimeVariables: variables.filter((v) => v.kind === 'runtime').map((v) => v.name),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
describe('utils/catalog', () => {
|
|
29
|
+
it('classifies pinned / runtime / configurable / returns / magic slots from variable kinds', () => {
|
|
30
|
+
const workflow = tagged('deposit', [
|
|
31
|
+
{ name: 'router', kind: 'pinned' },
|
|
32
|
+
{ name: 'maxFee', kind: 'configurable' },
|
|
33
|
+
{ name: 'amount', kind: 'runtime' },
|
|
34
|
+
], [
|
|
35
|
+
{
|
|
36
|
+
target: '$router',
|
|
37
|
+
selector: 'function deposit(uint256,uint256)',
|
|
38
|
+
inputs: [
|
|
39
|
+
{ parameter: 'uint256', label: 'Amount', input: ['$amount'] },
|
|
40
|
+
{ parameter: 'uint256', label: 'Max fee', input: ['$maxFee'] },
|
|
41
|
+
],
|
|
42
|
+
returns: '$sharesReceived',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
target: '$onOffRamp',
|
|
46
|
+
selector: 'function send(uint256,address)',
|
|
47
|
+
inputs: [
|
|
48
|
+
{ parameter: 'uint256', label: 'Shares', input: ['$sharesReceived'] },
|
|
49
|
+
{ parameter: 'address', label: 'Receiver', input: ['$executor'] },
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
], { router: ADDRESS_A });
|
|
53
|
+
const definition = buildWorkflowDefinitionFromCatalog(workflow);
|
|
54
|
+
expect(definition.runtimeVariables).to.deep.equal(['amount']);
|
|
55
|
+
expect(definition.actions[1].target).to.deep.equal({ type: 'magic', key: '$onOffRamp' });
|
|
56
|
+
// amount → runtime, maxFee → configurable (keyed by name), sharesReceived → computed runtime,
|
|
57
|
+
// executor → magic.
|
|
58
|
+
expect(definition.state[0]).to.deep.include({ type: 'runtime', key: 'amount', parameter: 'uint256' });
|
|
59
|
+
expect(definition.state[1]).to.deep.include({ type: 'configurable', key: 'maxFee', parameter: 'uint256' });
|
|
60
|
+
expect(definition.state[2]).to.deep.include({ type: 'runtime', key: 'sharesReceived' });
|
|
61
|
+
expect(definition.state[3]).to.deep.equal({ type: 'magic', key: '$executor' });
|
|
62
|
+
});
|
|
63
|
+
it('throws on an empty input array that is not a useTemplate', () => {
|
|
64
|
+
const workflow = tagged('bad-empty', [{ name: 'router', kind: 'pinned' }], [
|
|
65
|
+
{
|
|
66
|
+
target: '$router',
|
|
67
|
+
selector: 'function deposit(uint256)',
|
|
68
|
+
inputs: [{ parameter: 'uint256', label: 'Amount', input: [] }],
|
|
69
|
+
},
|
|
70
|
+
], { router: ADDRESS_A });
|
|
71
|
+
expect(() => buildWorkflowDefinitionFromCatalog(workflow)).to.throw('has an empty input');
|
|
72
|
+
});
|
|
73
|
+
it('throws when a pinned variable has no value in workflow.variables', () => {
|
|
74
|
+
const workflow = tagged('missing-pinned', [{ name: 'router', kind: 'pinned' }], [
|
|
75
|
+
{
|
|
76
|
+
target: '$router',
|
|
77
|
+
selector: 'function poke(address)',
|
|
78
|
+
inputs: [{ parameter: 'address', label: 'Router', input: ['$router'] }],
|
|
79
|
+
},
|
|
80
|
+
], {});
|
|
81
|
+
expect(() => buildWorkflowDefinitionFromCatalog(workflow)).to.throw('pinned variable "router" has no value');
|
|
82
|
+
});
|
|
83
|
+
it('uses FLAG_RAW for non-variable-length dynamic types (tuple arrays) sourced from a configurable', () => {
|
|
84
|
+
const selector = toFunctionSelector('function open(uint64,bytes16,(address,uint256)[])');
|
|
85
|
+
const workflow = tagged('slippage-open', [
|
|
86
|
+
{ name: 'guard', kind: 'pinned' },
|
|
87
|
+
{ name: 'slippageAssets', kind: 'configurable' },
|
|
88
|
+
], [
|
|
89
|
+
{
|
|
90
|
+
target: '$guard',
|
|
91
|
+
selector: 'function open(uint64,bytes16,(address,uint256)[])',
|
|
92
|
+
inputs: [
|
|
93
|
+
{ parameter: 'uint64', label: 'Pool ID', input: ['$poolId'] },
|
|
94
|
+
{ parameter: 'bytes16', label: 'SC ID', input: ['$scId'] },
|
|
95
|
+
{ parameter: '(address,uint256)[]', label: 'Assets', input: ['$slippageAssets'] },
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
], { guard: ADDRESS_A });
|
|
99
|
+
const definition = buildWorkflowDefinitionFromCatalog(workflow);
|
|
100
|
+
expect(definition.actions[0]).to.deep.include({ target: ADDRESS_A, selector });
|
|
101
|
+
expect(definition.actions[0].rawMode).to.equal(true);
|
|
102
|
+
expect(definition.actions[0].inputs).to.deep.equal([3]);
|
|
103
|
+
expect(definition.state[2]).to.deep.include({ type: 'configurable', key: 'slippageAssets', parameter: '(address,uint256)[]' });
|
|
104
|
+
expect(definition.state[3]).to.deep.equal({
|
|
105
|
+
type: 'rawcalldata',
|
|
106
|
+
selector,
|
|
107
|
+
parameterTypes: ['uint64', 'bytes16', '(address,uint256)[]'],
|
|
108
|
+
sourceSlots: [0, 1, 2],
|
|
109
|
+
actionName: 'function open(uint64,bytes16,(address,uint256)[])',
|
|
110
|
+
actionIndex: 0,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
it('encodes a pinned bytes literal in the inner ABI form via the 0x80 specifier (no FLAG_RAW)', () => {
|
|
114
|
+
const hookData = '0x636374702d686f6f6b2d646174612d30303030303030303030303030303031';
|
|
115
|
+
const workflow = tagged('cctp_send_auto', [
|
|
116
|
+
{ name: 'messenger', kind: 'pinned' },
|
|
117
|
+
{ name: 'hookData', kind: 'pinned' },
|
|
118
|
+
], [
|
|
119
|
+
{
|
|
120
|
+
target: '$messenger',
|
|
121
|
+
selector: 'function depositForBurnWithHook(uint256,uint32,bytes32,address,bytes32,uint256,uint32,bytes)',
|
|
122
|
+
inputs: [
|
|
123
|
+
{ parameter: 'uint256', label: 'Amount', input: ['100'] },
|
|
124
|
+
{ parameter: 'uint32', label: 'Destination domain', input: ['0'] },
|
|
125
|
+
{ parameter: 'bytes32', label: 'Mint recipient', input: ['0x0000000000000000000000002222222222222222222222222222222222222222'] },
|
|
126
|
+
{ parameter: 'address', label: 'Burn token', input: [ADDRESS_B] },
|
|
127
|
+
{ parameter: 'bytes32', label: 'Destination caller', input: ['0x0000000000000000000000001111111111111111111111111111111111111111'] },
|
|
128
|
+
{ parameter: 'uint256', label: 'Max fee', input: ['0'] },
|
|
129
|
+
{ parameter: 'uint32', label: 'Min finality threshold', input: ['1000'] },
|
|
130
|
+
{ parameter: 'bytes', label: 'Hook data', input: ['$hookData'] },
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
], { messenger: ADDRESS_A, hookData });
|
|
134
|
+
const definition = buildWorkflowDefinitionFromCatalog(workflow);
|
|
135
|
+
expect(definition.actions[0].rawMode).to.equal(undefined);
|
|
136
|
+
// Inner ABI form: 31-byte value → length 0x1f + 32-byte padded data.
|
|
137
|
+
expect(definition.state[5]).to.deep.equal({
|
|
138
|
+
type: 'literal',
|
|
139
|
+
value: '0x000000000000000000000000000000000000000000000000000000000000001f636374702d686f6f6b2d646174612d3030303030303030303030303030303100',
|
|
140
|
+
});
|
|
141
|
+
expect(definition.actions[0].inputs).to.deep.equal([0, 1, 2, 2, 3, 1, 4, 0x80 | 5]);
|
|
142
|
+
expect(definition.state.every((s) => s.type !== 'rawcalldata')).to.equal(true);
|
|
143
|
+
});
|
|
144
|
+
it('encodes a configurable bytes parameter as its own slot via the 0x80 specifier (no FLAG_RAW)', () => {
|
|
145
|
+
const workflow = tagged('cctp_send_auto', [
|
|
146
|
+
{ name: 'messenger', kind: 'pinned' },
|
|
147
|
+
{ name: 'hookData', kind: 'configurable' },
|
|
148
|
+
{ name: 'amount', kind: 'runtime' },
|
|
149
|
+
], [
|
|
150
|
+
{
|
|
151
|
+
target: '$messenger',
|
|
152
|
+
selector: 'function depositForBurnWithHook(uint256,bytes)',
|
|
153
|
+
inputs: [
|
|
154
|
+
{ parameter: 'uint256', label: 'Amount', input: ['$amount'] },
|
|
155
|
+
{ parameter: 'bytes', label: 'Hook data', input: ['$hookData'] },
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
], { messenger: ADDRESS_A });
|
|
159
|
+
const definition = buildWorkflowDefinitionFromCatalog(workflow);
|
|
160
|
+
expect(definition.actions[0].rawMode).to.equal(undefined);
|
|
161
|
+
expect(definition.state[0]).to.deep.include({ type: 'runtime', key: 'amount' });
|
|
162
|
+
expect(definition.state[1]).to.deep.include({ type: 'configurable', key: 'hookData', parameter: 'bytes' });
|
|
163
|
+
expect(definition.actions[0].inputs).to.deep.equal([0, 0x80 | 1]);
|
|
164
|
+
expect(definition.state.every((s) => s.type !== 'rawcalldata')).to.equal(true);
|
|
165
|
+
});
|
|
166
|
+
it('encodes a runtime bytes argument via the 0x80 specifier, not FLAG_RAW (selector pinned)', () => {
|
|
167
|
+
// A runtime bytes argument keeps the call's selector in the (hashed) command word — the
|
|
168
|
+
// strategist varies only the argument, never the function (audit #18 / SECURITY.md §11).
|
|
169
|
+
const workflow = tagged('runtime-bytes', [
|
|
170
|
+
{ name: 'target', kind: 'pinned' },
|
|
171
|
+
{ name: 'amount', kind: 'runtime' },
|
|
172
|
+
{ name: 'payload', kind: 'runtime' },
|
|
173
|
+
], [
|
|
174
|
+
{
|
|
175
|
+
target: '$target',
|
|
176
|
+
selector: 'function call(uint256,bytes)',
|
|
177
|
+
inputs: [
|
|
178
|
+
{ parameter: 'uint256', label: 'Amount', input: ['$amount'] },
|
|
179
|
+
{ parameter: 'bytes', label: 'Payload', input: ['$payload'] },
|
|
180
|
+
],
|
|
181
|
+
},
|
|
182
|
+
], { target: ADDRESS_A });
|
|
183
|
+
const definition = buildWorkflowDefinitionFromCatalog(workflow);
|
|
184
|
+
expect(definition.actions[0].rawMode).to.equal(undefined);
|
|
185
|
+
expect(definition.actions[0].inputs).to.deep.equal([0, 0x80 | 1]);
|
|
186
|
+
expect(definition.state.every((s) => s.type !== 'rawcalldata')).to.equal(true);
|
|
187
|
+
expect(definition.state[1]).to.deep.include({ type: 'runtime', key: 'payload', parameter: 'bytes' });
|
|
188
|
+
});
|
|
189
|
+
it('injects useTemplate bytes inputs as pinned callback script data', () => {
|
|
190
|
+
const callbackVariables = [
|
|
191
|
+
{ name: 'data', kind: 'configurable' },
|
|
192
|
+
{ name: 'asset', kind: 'param' },
|
|
193
|
+
{ name: 'vault', kind: 'param' },
|
|
194
|
+
];
|
|
195
|
+
const workflow = {
|
|
196
|
+
workflowRef: 'morpho-loop',
|
|
197
|
+
name: 'Morpho loop',
|
|
198
|
+
template: 'morpho_loop_deposit',
|
|
199
|
+
chainId: 1,
|
|
200
|
+
variables: { flashLoanHelper: ADDRESS_A, pool: ADDRESS_B, asset: ADDRESS_C, vault: ADDRESS_D },
|
|
201
|
+
workflowId: '0x01',
|
|
202
|
+
version: 1,
|
|
203
|
+
runtimeVariables: ['amount'],
|
|
204
|
+
templates: {
|
|
205
|
+
morpho_loop_deposit: {
|
|
206
|
+
variables: [
|
|
207
|
+
{ name: 'flashLoanHelper', kind: 'pinned' },
|
|
208
|
+
{ name: 'pool', kind: 'pinned' },
|
|
209
|
+
{ name: 'asset', kind: 'pinned' },
|
|
210
|
+
{ name: 'vault', kind: 'pinned' },
|
|
211
|
+
{ name: 'amount', kind: 'runtime' },
|
|
212
|
+
],
|
|
213
|
+
actions: [],
|
|
214
|
+
},
|
|
215
|
+
morpho_loop_deposit_callback: {
|
|
216
|
+
variables: callbackVariables,
|
|
217
|
+
actions: [
|
|
218
|
+
{
|
|
219
|
+
target: '$asset',
|
|
220
|
+
selector: 'function balanceOf(address)',
|
|
221
|
+
inputs: [{ parameter: 'address', label: 'Account', input: ['$onchainPM'] }],
|
|
222
|
+
returns: '$totalAmount',
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
target: '$vault',
|
|
226
|
+
selector: 'function deposit(uint256,address)',
|
|
227
|
+
inputs: [
|
|
228
|
+
{ parameter: 'uint256', label: 'Assets', input: ['$totalAmount'] },
|
|
229
|
+
{ parameter: 'address', label: 'Receiver', input: ['$onchainPM'] },
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
target: '$vault',
|
|
234
|
+
selector: 'function supplyCollateral(uint256,bytes)',
|
|
235
|
+
inputs: [
|
|
236
|
+
{ parameter: 'uint256', label: 'Shares', input: ['$totalAmount'] },
|
|
237
|
+
{ parameter: 'bytes', label: 'Data', input: ['$data'] },
|
|
238
|
+
],
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
actions: [
|
|
244
|
+
{
|
|
245
|
+
target: '$flashLoanHelper',
|
|
246
|
+
selector: 'function requestFlashLoan(address,address,uint256,address,bytes)',
|
|
247
|
+
inputs: [
|
|
248
|
+
{ parameter: 'address', label: 'Aave Pool', input: ['$pool'] },
|
|
249
|
+
{ parameter: 'address', label: 'Token', input: ['$asset'] },
|
|
250
|
+
{ parameter: 'uint256', label: 'Amount', input: ['$amount'] },
|
|
251
|
+
{ parameter: 'address', label: 'OnchainPM', input: ['$onchainPM'] },
|
|
252
|
+
{
|
|
253
|
+
parameter: 'bytes',
|
|
254
|
+
label: 'Callback data',
|
|
255
|
+
input: [],
|
|
256
|
+
useTemplate: { template: 'morpho_loop_deposit_callback', map: { asset: '$asset', vault: '$vault' } },
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
};
|
|
262
|
+
const definition = buildWorkflowDefinitionFromCatalog(workflow);
|
|
263
|
+
const callbackInput = definition.actions[0].inputs[4];
|
|
264
|
+
const callbackSlot = callbackInput & 0x7f;
|
|
265
|
+
expect(definition.actions[0].rawMode).to.equal(undefined);
|
|
266
|
+
expect(callbackInput).to.equal(0x80 | callbackSlot);
|
|
267
|
+
expect(definition.state[callbackSlot]).to.deep.include({ type: 'template', label: 'Callback data', actionIndex: 0, inputIndex: 4 });
|
|
268
|
+
const templateSlot = definition.state[callbackSlot];
|
|
269
|
+
if (!templateSlot || templateSlot.type !== 'template')
|
|
270
|
+
throw new Error('Expected callback slot to be a template slot');
|
|
271
|
+
expect(templateSlot.workflow.actions[2].rawMode).to.equal(undefined);
|
|
272
|
+
expect(definition.runtimeVariables).to.deep.equal(['amount']);
|
|
273
|
+
const { state, stateBitmap } = buildScript(definition, {
|
|
274
|
+
poolContext: { $onchainPM: ONCHAIN_PM_BYTES32 },
|
|
275
|
+
// The callback's `data` is configurable — supply an empty value (encoded as length-0 bytes).
|
|
276
|
+
configurableValues: { data: `0x${'00'.repeat(32)}` },
|
|
277
|
+
});
|
|
278
|
+
expect((stateBitmap & (1n << BigInt(callbackSlot))) !== 0n).to.equal(true);
|
|
279
|
+
// weiroll copies state[idx] verbatim into the parent's calldata at the bytes-input offset
|
|
280
|
+
// (no length-prefix word), so state[callbackSlot] is [length][abi-encoded callback].
|
|
281
|
+
const callbackSlotData = state[callbackSlot];
|
|
282
|
+
const callbackBytes = `0x${callbackSlotData.slice(2 + 64)}`;
|
|
283
|
+
const declaredLength = Number(BigInt(`0x${callbackSlotData.slice(2, 2 + 64)}`));
|
|
284
|
+
expect(declaredLength).to.equal((callbackBytes.length - 2) / 2);
|
|
285
|
+
const [commands, callbackState, callbackStateBitmap] = decodeAbiParameters([{ type: 'bytes32[]' }, { type: 'bytes[]' }, { type: 'uint128' }], callbackBytes);
|
|
286
|
+
expect(Array.isArray(commands)).to.equal(true);
|
|
287
|
+
expect(Array.isArray(callbackState)).to.equal(true);
|
|
288
|
+
expect(typeof callbackStateBitmap).to.equal('bigint');
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
//# sourceMappingURL=catalog.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.test.js","sourceRoot":"","sources":["../../src/utils/catalog.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { HexString } from '../types/index.js';
|
|
2
|
+
/** Pre/post execution hook committed to alongside the script. */
|
|
3
|
+
export interface Callback {
|
|
4
|
+
/** Expected script hash for the callback, from a nested computeScriptHash() call. */
|
|
5
|
+
hash: HexString;
|
|
6
|
+
/** Expected msg.sender when executeCallback() is invoked. */
|
|
7
|
+
caller: HexString;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Offline reimplementation of `OnchainPM.computeScriptHash()`.
|
|
11
|
+
*
|
|
12
|
+
* Avoids a live RPC call so scripts can be built and hashed without a running
|
|
13
|
+
* node. Matches the on-chain `pure` function exactly:
|
|
14
|
+
*
|
|
15
|
+
* ```solidity
|
|
16
|
+
* keccak256(abi.encodePacked(
|
|
17
|
+
* keccak256(abi.encodePacked(commands)),
|
|
18
|
+
* _hashBitmapSlots(state, stateBitmap),
|
|
19
|
+
* stateBitmap, // uint128 — 16 bytes packed
|
|
20
|
+
* state.length, // uint256 — 32 bytes packed
|
|
21
|
+
* keccak256(abi.encode(callbacks))
|
|
22
|
+
* ))
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* **Key property**: state slots whose bitmap bit is 0 (runtime) are excluded
|
|
26
|
+
* from the hash. Runtime values can therefore change at execution time without
|
|
27
|
+
* invalidating the Merkle proof.
|
|
28
|
+
*
|
|
29
|
+
* Pass `callbacks = []` for standard (non-callback) workflows.
|
|
30
|
+
*/
|
|
31
|
+
export declare function computeScriptHash(commands: HexString[], state: HexString[], stateBitmap: bigint, callbacks: Callback[]): HexString;
|
|
32
|
+
//# sourceMappingURL=scriptHash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scriptHash.d.ts","sourceRoot":"","sources":["../../src/utils/scriptHash.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAMlD,iEAAiE;AACjE,MAAM,WAAW,QAAQ;IACvB,qFAAqF;IACrF,IAAI,EAAE,SAAS,CAAA;IACf,6DAA6D;IAC7D,MAAM,EAAE,SAAS,CAAA;CAClB;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,SAAS,EAAE,EACrB,KAAK,EAAE,SAAS,EAAE,EAClB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,QAAQ,EAAE,GACpB,SAAS,CAiCX"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { concat, encodeAbiParameters, encodePacked, keccak256 } from 'viem';
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// computeScriptHash
|
|
4
|
+
// ---------------------------------------------------------------------------
|
|
5
|
+
/**
|
|
6
|
+
* Offline reimplementation of `OnchainPM.computeScriptHash()`.
|
|
7
|
+
*
|
|
8
|
+
* Avoids a live RPC call so scripts can be built and hashed without a running
|
|
9
|
+
* node. Matches the on-chain `pure` function exactly:
|
|
10
|
+
*
|
|
11
|
+
* ```solidity
|
|
12
|
+
* keccak256(abi.encodePacked(
|
|
13
|
+
* keccak256(abi.encodePacked(commands)),
|
|
14
|
+
* _hashBitmapSlots(state, stateBitmap),
|
|
15
|
+
* stateBitmap, // uint128 — 16 bytes packed
|
|
16
|
+
* state.length, // uint256 — 32 bytes packed
|
|
17
|
+
* keccak256(abi.encode(callbacks))
|
|
18
|
+
* ))
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* **Key property**: state slots whose bitmap bit is 0 (runtime) are excluded
|
|
22
|
+
* from the hash. Runtime values can therefore change at execution time without
|
|
23
|
+
* invalidating the Merkle proof.
|
|
24
|
+
*
|
|
25
|
+
* Pass `callbacks = []` for standard (non-callback) workflows.
|
|
26
|
+
*/
|
|
27
|
+
export function computeScriptHash(commands, state, stateBitmap, callbacks) {
|
|
28
|
+
// 1. keccak256(abi.encodePacked(commands))
|
|
29
|
+
// Each command is bytes32; packed = raw concatenation, no length prefix.
|
|
30
|
+
const commandsHash = keccak256(commands.length > 0 ? concat(commands) : '0x');
|
|
31
|
+
// 2. _hashBitmapSlots(state, stateBitmap)
|
|
32
|
+
// Only pinned slots (bitmap bit = 1) contribute to this hash.
|
|
33
|
+
const bitmapSlotsHash = hashBitmapSlots(state, stateBitmap);
|
|
34
|
+
// 3. keccak256(abi.encode(callbacks))
|
|
35
|
+
// abi.encode of an empty Callback[] is a well-defined 64-byte constant.
|
|
36
|
+
const callbacksHash = keccak256(encodeAbiParameters([
|
|
37
|
+
{
|
|
38
|
+
type: 'tuple[]',
|
|
39
|
+
components: [
|
|
40
|
+
{ name: 'hash', type: 'bytes32' },
|
|
41
|
+
{ name: 'caller', type: 'address' },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
], [callbacks.map((c) => ({ hash: c.hash, caller: c.caller }))]));
|
|
45
|
+
// Final: keccak256(abi.encodePacked(commandsHash, bitmapSlotsHash, stateBitmap, state.length, callbacksHash))
|
|
46
|
+
return keccak256(encodePacked(['bytes32', 'bytes32', 'uint128', 'uint256', 'bytes32'], [commandsHash, bitmapSlotsHash, stateBitmap, BigInt(state.length), callbacksHash]));
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Internal helpers
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
/**
|
|
52
|
+
* Replicates `OnchainPM._hashBitmapSlots`.
|
|
53
|
+
*
|
|
54
|
+
* For each state[i] where bit i is set in stateBitmap:
|
|
55
|
+
* 1. Hash state[i] individually with keccak256
|
|
56
|
+
* Then hash the resulting array of hashes with keccak256(abi.encodePacked(hashes)).
|
|
57
|
+
*/
|
|
58
|
+
function hashBitmapSlots(state, stateBitmap) {
|
|
59
|
+
const pinnedHashes = [];
|
|
60
|
+
for (const [i, slot] of state.entries()) {
|
|
61
|
+
if ((stateBitmap >> BigInt(i)) & 1n) {
|
|
62
|
+
pinnedHashes.push(keccak256(slot));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return keccak256(pinnedHashes.length > 0 ? concat(pinnedHashes) : '0x');
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=scriptHash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scriptHash.js","sourceRoot":"","sources":["../../src/utils/scriptHash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,MAAM,CAAA;AAe3E,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAqB,EACrB,KAAkB,EAClB,WAAmB,EACnB,SAAqB;IAErB,2CAA2C;IAC3C,4EAA4E;IAC5E,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAE7E,0CAA0C;IAC1C,iEAAiE;IACjE,MAAM,eAAe,GAAG,eAAe,CAAC,KAAK,EAAE,WAAW,CAAC,CAAA;IAE3D,sCAAsC;IACtC,2EAA2E;IAC3E,MAAM,aAAa,GAAG,SAAS,CAC7B,mBAAmB,CACjB;QACE;YACE,IAAI,EAAE,SAAS;YACf,UAAU,EAAE;gBACV,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;gBACjC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE;aACpC;SACF;KACF,EACD,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAC7D,CACF,CAAA;IAED,8GAA8G;IAC9G,OAAO,SAAS,CACd,YAAY,CACV,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EACvD,CAAC,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC,CAClF,CACW,CAAA;AAChB,CAAC;AAED,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,KAAkB,EAAE,WAAmB;IAC9D,MAAM,YAAY,GAAgB,EAAE,CAAA;IACpC,KAAK,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QACxC,IAAI,CAAC,WAAW,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC;YACpC,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QACpC,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;AACzE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scriptHash.test.d.ts","sourceRoot":"","sources":["../../src/utils/scriptHash.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { computeScriptHash } from './scriptHash.js';
|
|
3
|
+
// Reusable fixtures
|
|
4
|
+
const CMD = '0xaabbccdd01000102ffffff031234567890123456789012345678901234567890';
|
|
5
|
+
const SLOT_A = '0x0000000000000000000000000000000000000000000000000000000000000001';
|
|
6
|
+
const SLOT_B = '0x0000000000000000000000000000000000000000000000000000000000000002';
|
|
7
|
+
const SLOT_C = '0x0000000000000000000000000000000000000000000000000000000000000003';
|
|
8
|
+
describe('utils/scriptHash', () => {
|
|
9
|
+
describe('computeScriptHash', () => {
|
|
10
|
+
it('returns a 32-byte hex string', () => {
|
|
11
|
+
const hash = computeScriptHash([CMD], [SLOT_A], 1n, []);
|
|
12
|
+
expect(hash).to.match(/^0x[0-9a-f]{64}$/);
|
|
13
|
+
});
|
|
14
|
+
it('is deterministic for identical inputs', () => {
|
|
15
|
+
const h1 = computeScriptHash([CMD], [SLOT_A], 1n, []);
|
|
16
|
+
const h2 = computeScriptHash([CMD], [SLOT_A], 1n, []);
|
|
17
|
+
expect(h1).to.equal(h2);
|
|
18
|
+
});
|
|
19
|
+
it('works with empty commands, state, and callbacks', () => {
|
|
20
|
+
const hash = computeScriptHash([], [], 0n, []);
|
|
21
|
+
expect(hash).to.match(/^0x[0-9a-f]{64}$/);
|
|
22
|
+
});
|
|
23
|
+
it('changes when commands change', () => {
|
|
24
|
+
const h1 = computeScriptHash([CMD], [SLOT_A], 1n, []);
|
|
25
|
+
const cmd2 = CMD.replace('aabb', 'ccdd');
|
|
26
|
+
const h2 = computeScriptHash([cmd2], [SLOT_A], 1n, []);
|
|
27
|
+
expect(h1).to.not.equal(h2);
|
|
28
|
+
});
|
|
29
|
+
it('changes when a pinned state slot changes', () => {
|
|
30
|
+
// slot 0 is pinned (bitmap bit 0 = 1)
|
|
31
|
+
const h1 = computeScriptHash([CMD], [SLOT_A], 1n, []);
|
|
32
|
+
const h2 = computeScriptHash([CMD], [SLOT_B], 1n, []);
|
|
33
|
+
expect(h1).to.not.equal(h2);
|
|
34
|
+
});
|
|
35
|
+
it('does NOT change when a runtime state slot changes — key property', () => {
|
|
36
|
+
// state: [SLOT_A (pinned, bit 0), SLOT_B (runtime, bit 1 = 0)]
|
|
37
|
+
// Changing the runtime slot must not affect the hash.
|
|
38
|
+
const bitmap = 1n; // only bit 0 set
|
|
39
|
+
const h1 = computeScriptHash([CMD], [SLOT_A, SLOT_B], bitmap, []);
|
|
40
|
+
const h2 = computeScriptHash([CMD], [SLOT_A, SLOT_C], bitmap, []);
|
|
41
|
+
expect(h1).to.equal(h2);
|
|
42
|
+
});
|
|
43
|
+
it('does NOT change when all slots are runtime (bitmap = 0)', () => {
|
|
44
|
+
const h1 = computeScriptHash([CMD], [SLOT_A], 0n, []);
|
|
45
|
+
const h2 = computeScriptHash([CMD], [SLOT_B], 0n, []);
|
|
46
|
+
expect(h1).to.equal(h2);
|
|
47
|
+
});
|
|
48
|
+
it('changes when stateBitmap changes', () => {
|
|
49
|
+
// Pinning an extra slot changes the hash even if slot values are the same
|
|
50
|
+
const h1 = computeScriptHash([CMD], [SLOT_A, SLOT_B], 1n, []); // slot 0 pinned only
|
|
51
|
+
const h2 = computeScriptHash([CMD], [SLOT_A, SLOT_B], 3n, []); // slots 0+1 pinned
|
|
52
|
+
expect(h1).to.not.equal(h2);
|
|
53
|
+
});
|
|
54
|
+
it('changes when state.length changes, even if bitmap = 0', () => {
|
|
55
|
+
// state.length is packed directly into the hash
|
|
56
|
+
const h1 = computeScriptHash([CMD], [SLOT_A], 0n, []);
|
|
57
|
+
const h2 = computeScriptHash([CMD], [SLOT_A, SLOT_B], 0n, []);
|
|
58
|
+
expect(h1).to.not.equal(h2);
|
|
59
|
+
});
|
|
60
|
+
it('changes when a callback is added', () => {
|
|
61
|
+
const h1 = computeScriptHash([CMD], [SLOT_A], 1n, []);
|
|
62
|
+
const callback = {
|
|
63
|
+
hash: '0x1111111111111111111111111111111111111111111111111111111111111111',
|
|
64
|
+
caller: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
|
|
65
|
+
};
|
|
66
|
+
const h2 = computeScriptHash([CMD], [SLOT_A], 1n, [callback]);
|
|
67
|
+
expect(h1).to.not.equal(h2);
|
|
68
|
+
});
|
|
69
|
+
it('changes when a callback hash changes', () => {
|
|
70
|
+
const cb1 = {
|
|
71
|
+
hash: '0x1111111111111111111111111111111111111111111111111111111111111111',
|
|
72
|
+
caller: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
|
|
73
|
+
};
|
|
74
|
+
const cb2 = {
|
|
75
|
+
hash: '0x2222222222222222222222222222222222222222222222222222222222222222',
|
|
76
|
+
caller: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
|
|
77
|
+
};
|
|
78
|
+
const h1 = computeScriptHash([CMD], [SLOT_A], 1n, [cb1]);
|
|
79
|
+
const h2 = computeScriptHash([CMD], [SLOT_A], 1n, [cb2]);
|
|
80
|
+
expect(h1).to.not.equal(h2);
|
|
81
|
+
});
|
|
82
|
+
it('correctly isolates pinned slots across mixed bitmap', () => {
|
|
83
|
+
// slots: [A(pinned), B(runtime), C(pinned)] — bitmap = 0b101 = 5
|
|
84
|
+
// Changing slot 1 (B, runtime) must not change the hash
|
|
85
|
+
const bitmap = 5n; // bits 0 and 2 set
|
|
86
|
+
const state1 = [SLOT_A, SLOT_B, SLOT_C];
|
|
87
|
+
const state2 = [SLOT_A, SLOT_C, SLOT_C]; // slot 1 changed to C
|
|
88
|
+
expect(computeScriptHash([CMD], state1, bitmap, []))
|
|
89
|
+
.to.equal(computeScriptHash([CMD], state2, bitmap, []));
|
|
90
|
+
// But changing slot 0 (A, pinned) must change the hash
|
|
91
|
+
const state3 = [SLOT_B, SLOT_B, SLOT_C]; // slot 0 changed to B
|
|
92
|
+
expect(computeScriptHash([CMD], state1, bitmap, []))
|
|
93
|
+
.to.not.equal(computeScriptHash([CMD], state3, bitmap, []));
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=scriptHash.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scriptHash.test.js","sourceRoot":"","sources":["../../src/utils/scriptHash.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { HexString } from '../types/index.js';
|
|
2
|
+
import type { PoolMetadata } from '../types/poolMetadata.js';
|
|
3
|
+
import type { PoolContext } from './weiroll.js';
|
|
4
|
+
/**
|
|
5
|
+
* All well-known magic variable keys. Each is prefixed with `$` to
|
|
6
|
+
* distinguish them from protocol-specific manifest variables.
|
|
7
|
+
*
|
|
8
|
+
* Magic variables are resolved automatically by the SDK from pool metadata;
|
|
9
|
+
* they are always pinned (stateBitmap bit = 1).
|
|
10
|
+
*/
|
|
11
|
+
export declare const MAGIC_VARIABLE_KEYS: readonly ["$executor", "$onchainPM", "$poolEscrow", "$onOffRamp", "$poolId", "$scId", "$accountingTokenId", "$accountingTokenAssetId"];
|
|
12
|
+
export type MagicVariableKey = (typeof MAGIC_VARIABLE_KEYS)[number];
|
|
13
|
+
/**
|
|
14
|
+
* Typed inputs required to resolve the SDK's magic variables.
|
|
15
|
+
*
|
|
16
|
+
* All values must be ABI-encoded as 32-byte hex strings so they can be
|
|
17
|
+
* stored directly in the weiroll state array (bytes32 slots).
|
|
18
|
+
*
|
|
19
|
+
* Typical encoding per variable:
|
|
20
|
+
* - addresses (`$executor`, `$poolEscrow`, `$onOffRamp`): left-zero-padded to 32 bytes
|
|
21
|
+
* - `$poolId`: uint64 value encoded as uint256 (32 bytes)
|
|
22
|
+
* - `$scId`: bytes16 value right-zero-padded to 32 bytes
|
|
23
|
+
* - `$accountingTokenId`, `$accountingTokenAssetId`: uint256 (32 bytes)
|
|
24
|
+
*/
|
|
25
|
+
export interface MagicVariableContext {
|
|
26
|
+
/** Address of the workflow executor for this pool, typically the OnchainPM. */
|
|
27
|
+
executor: HexString;
|
|
28
|
+
/** Address of the pool escrow contract. */
|
|
29
|
+
poolEscrow: HexString;
|
|
30
|
+
/** Address of the on/off ramp manager for the share class. */
|
|
31
|
+
onOffRamp: HexString;
|
|
32
|
+
/** Pool ID (uint64) ABI-encoded as a 32-byte value. */
|
|
33
|
+
poolId: HexString;
|
|
34
|
+
/** Share class ID (bytes16) right-zero-padded to 32 bytes. */
|
|
35
|
+
scId: HexString;
|
|
36
|
+
/** ERC6909 accounting token ID for the share class, as a 32-byte value. */
|
|
37
|
+
accountingTokenId: HexString;
|
|
38
|
+
/** Asset ID of the accounting token, as a 32-byte value. */
|
|
39
|
+
accountingTokenAssetId: HexString;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Builds a `PoolContext` from a typed `MagicVariableContext` by mapping
|
|
43
|
+
* each `$`-prefixed magic variable key to its resolved value.
|
|
44
|
+
*
|
|
45
|
+
* Pass the returned object as `poolContext` in `buildScript()`:
|
|
46
|
+
*
|
|
47
|
+
* ```typescript
|
|
48
|
+
* const poolContext = resolveMagicVariables(ctx)
|
|
49
|
+
* const script = buildScript(workflow, { poolContext, configurableValues })
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @throws if any value is not a valid 32-byte ABI-encoded hex string
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveMagicVariables(context: MagicVariableContext): PoolContext;
|
|
55
|
+
/**
|
|
56
|
+
* Returns a human-readable `{ value, label }` pair for a resolved variable.
|
|
57
|
+
*
|
|
58
|
+
* Used by the backend to enrich API responses so the frontend never displays
|
|
59
|
+
* raw on-chain data. Example:
|
|
60
|
+
*
|
|
61
|
+
* ```typescript
|
|
62
|
+
* resolveVariableLabel('$scId', '0x00010000000000010000000000000001', meta)
|
|
63
|
+
* // → { value: '0x000100...', label: 'JTRSY' }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* Label resolution priority:
|
|
67
|
+
* 1. `poolMetadata.addressLabels[value]` — pool-manager-maintained free-form map
|
|
68
|
+
* 2. Key-specific fallbacks (e.g. pool name for `$poolId`)
|
|
69
|
+
* 3. Raw hex string as final fallback
|
|
70
|
+
*
|
|
71
|
+
* Pool managers can register labels for any address or slot value via the
|
|
72
|
+
* `addressLabels` field of the pool metadata to customise what the UI shows.
|
|
73
|
+
*/
|
|
74
|
+
export declare function resolveVariableLabel(key: string, value: HexString, poolMetadata: PoolMetadata): {
|
|
75
|
+
value: HexString;
|
|
76
|
+
label: string;
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=variables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../../src/utils/variables.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAM/C;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,wIAStB,CAAA;AAEV,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAA;AAMnE;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,oBAAoB;IACnC,+EAA+E;IAC/E,QAAQ,EAAE,SAAS,CAAA;IACnB,2CAA2C;IAC3C,UAAU,EAAE,SAAS,CAAA;IACrB,8DAA8D;IAC9D,SAAS,EAAE,SAAS,CAAA;IACpB,uDAAuD;IACvD,MAAM,EAAE,SAAS,CAAA;IACjB,8DAA8D;IAC9D,IAAI,EAAE,SAAS,CAAA;IACf,2EAA2E;IAC3E,iBAAiB,EAAE,SAAS,CAAA;IAC5B,4DAA4D;IAC5D,sBAAsB,EAAE,SAAS,CAAA;CAClC;AAkBD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,oBAAoB,GAAG,WAAW,CAqBhF;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,SAAS,EAChB,YAAY,EAAE,YAAY,GACzB;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAoBrC"}
|