sta-sdk 0.1.0
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/LICENSE +21 -0
- package/README.md +107 -0
- package/dist/index.cjs +498 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +484 -0
- package/dist/index.d.ts +484 -0
- package/dist/index.js +462 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Smart Treasury Account contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# sta-sdk
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for the Smart Treasury Account (STA) Soroban contracts:
|
|
4
|
+
`smart_account` custom-authorization (Entry A / Entry B) construction,
|
|
5
|
+
transaction preparation (prepare → simulate → sign → submit → poll), typed
|
|
6
|
+
`#[contractevent]` parsing, and typed state reads (policy version, replay
|
|
7
|
+
nonce, recovery state).
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install sta-sdk @stellar/stellar-sdk
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`@stellar/stellar-sdk` (`>=16.0.0`) is a peer dependency — install it
|
|
16
|
+
yourself so your app controls the version and there is only ever one copy
|
|
17
|
+
of its classes (`Address`, `xdr.ScVal`, ...) loaded.
|
|
18
|
+
|
|
19
|
+
## Why this SDK hand-encodes calls instead of using generated bindings
|
|
20
|
+
|
|
21
|
+
The Stellar CLI's `stellar contract bindings typescript` output is pinned
|
|
22
|
+
to whatever `@stellar/stellar-sdk` major was current when it was
|
|
23
|
+
generated. Depending on those generated bindings directly here would force
|
|
24
|
+
every consumer of this SDK onto that exact major, and loading two majors
|
|
25
|
+
of the same runtime classes in one bundle risks `instanceof` mismatches.
|
|
26
|
+
So this package encodes `AuthPayload` structs, call args, and typed reads
|
|
27
|
+
by hand against the contracts' real `#[contracttype]`/`#[contractevent]`
|
|
28
|
+
definitions, verified live — see each module's doc comment for specifics.
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { TESTNET, prepareTransferPayment, signAndSubmit, readPolicyVersion } from "sta-sdk";
|
|
34
|
+
import { Keypair } from "@stellar/stellar-sdk";
|
|
35
|
+
|
|
36
|
+
const signer = Keypair.fromSecret(process.env.SIGNER_SECRET!);
|
|
37
|
+
const expectedPolicyVersion = await readPolicyVersion(TESTNET, signer.publicKey());
|
|
38
|
+
|
|
39
|
+
const tx = await prepareTransferPayment(
|
|
40
|
+
{
|
|
41
|
+
net: TESTNET,
|
|
42
|
+
feeSourceAddress: signer.publicKey(),
|
|
43
|
+
signerAddress: signer.publicKey(),
|
|
44
|
+
sign: signer,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
asset: "CASSET...",
|
|
48
|
+
destination: "GDESTINATION...",
|
|
49
|
+
amount: 100_0000000n,
|
|
50
|
+
nonce: BigInt(Date.now()),
|
|
51
|
+
expectedPolicyVersion,
|
|
52
|
+
},
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const result = await signAndSubmit(TESTNET, tx, signer);
|
|
56
|
+
console.log("ledger:", result.ledger);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
See [`examples/`](./examples) for one runnable, documented example per
|
|
60
|
+
flow: transfer, split payment, scheduled payment, and event parsing.
|
|
61
|
+
|
|
62
|
+
## Modules
|
|
63
|
+
|
|
64
|
+
| Module | Exports |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `config` | `NetworkConfig`, `TESTNET`, `buildMainnetConfig` |
|
|
67
|
+
| `auth` | `buildSmartAccountAuthEntries`, `buildExecutorAuthEntry`, auth-entry helpers |
|
|
68
|
+
| `payments` | `prepareTransferPayment`, `prepareSplitPayment`, `prepareScheduledPayment`, `prepareCancelScheduledPayment`, `signAndSubmit` |
|
|
69
|
+
| `events` | `parseContractEvent`, `parseContractEvents`, `findEvent` |
|
|
70
|
+
| `state` | typed reads: `AccountStatus`, `ContextRule`, `ScheduledIntent`, `RecoveryRequest`, `WasmHashes` |
|
|
71
|
+
|
|
72
|
+
## Versioning against a deployment
|
|
73
|
+
|
|
74
|
+
Each release states which contract deployment it targets. `TESTNET` in
|
|
75
|
+
`config.ts` is pinned to the currently-deployed testnet contract set (see
|
|
76
|
+
that module's doc comment for the source deployment record). Mainnet has
|
|
77
|
+
no deployment yet — `buildMainnetConfig` exists so wiring one in later is
|
|
78
|
+
a config call, not a code change; see its doc comment.
|
|
79
|
+
|
|
80
|
+
## Known issue — multi-signer context rules
|
|
81
|
+
|
|
82
|
+
`buildSmartAccountAuthEntries` builds Entry A + Entry B for a single
|
|
83
|
+
required signer. For a context rule with more than one required signer
|
|
84
|
+
(a real M-of-N threshold), calling it once per signer and attaching each
|
|
85
|
+
pair does **not** currently match the documented design (one shared
|
|
86
|
+
Entry A carrying all signers' keys, plus N Entry Bs collected against it).
|
|
87
|
+
Don't rely on multi-signer thresholds through this function until that's
|
|
88
|
+
fixed — see the doc comment on that function.
|
|
89
|
+
|
|
90
|
+
## Development
|
|
91
|
+
|
|
92
|
+
```sh
|
|
93
|
+
pnpm install
|
|
94
|
+
pnpm test
|
|
95
|
+
pnpm build
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Publishing
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
npm version <patch|minor|major>
|
|
102
|
+
npm publish
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`prepublishOnly` runs typecheck, tests, and build first. CI
|
|
106
|
+
(`.github/workflows/publish.yml`) publishes automatically on a pushed
|
|
107
|
+
`v*` tag, using the `NPM_TOKEN` repository secret.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var stellarSdk = require('@stellar/stellar-sdk');
|
|
4
|
+
|
|
5
|
+
// src/config.ts
|
|
6
|
+
var TESTNET = {
|
|
7
|
+
network: "testnet",
|
|
8
|
+
rpcUrl: "https://soroban-testnet.stellar.org",
|
|
9
|
+
networkPassphrase: "Test SDF Network ; September 2015",
|
|
10
|
+
contracts: {
|
|
11
|
+
smartAccount: "CD6GY4UUTNPW4TUV7LDL5SELN4BBHJG4KDDT3W6G23DY6XCGM75MULMQ",
|
|
12
|
+
policyEngine: "CCOP7NRMST5K6TL7FBDMX25LDEPW3DSFBOGBIKVFIDNAAZY7GBMVP3M4",
|
|
13
|
+
intentRegistry: "CAFIATSIZQSBILZJWVT4PVDXPVITJHLP6LPAVKDRHCA7I7XPZSLTRPUS",
|
|
14
|
+
recoveryManager: "CCHC4YKVYS3CAZUOUYWYTEMQ6TZDW75WB2BGENUC2CDWDX5RH7NMKZWU",
|
|
15
|
+
accountFactory: "CAQQTRRYNXIQGFVNCTMTBJDXW3PN7O44KPT7GWCCE4FRKTOHDBCWGUZO",
|
|
16
|
+
transferAdapter: "CBRYGIR3ORDW5LE6J7AVPSKRNTMRUYHD6FVPHQMJGPQLQ5FQUZ2U6GFH",
|
|
17
|
+
splitAdapter: "CBQA7UI7QN6RN4IZT7WPDHWTK2OO7J4FH2KMCVJGKMKVFGDURD63UQ7U"
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
var MAINNET_NETWORK_PASSPHRASE = "Public Global Stellar Network ; September 2015";
|
|
21
|
+
var MAINNET_RPC_URL_ENV = "STA_MAINNET_RPC_URL";
|
|
22
|
+
function buildMainnetConfig(contracts, rpcUrl = (typeof process !== "undefined" ? process.env?.[MAINNET_RPC_URL_ENV] : void 0) ?? "") {
|
|
23
|
+
if (!rpcUrl) {
|
|
24
|
+
throw new Error(
|
|
25
|
+
`Mainnet RPC URL not configured -- pass one explicitly to buildMainnetConfig, or set ${MAINNET_RPC_URL_ENV}. SDF hosts no free public mainnet endpoint; see https://developers.stellar.org/docs/data/apis/rpc/providers for ecosystem providers.`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
network: "mainnet",
|
|
30
|
+
rpcUrl,
|
|
31
|
+
networkPassphrase: MAINNET_NETWORK_PASSPHRASE,
|
|
32
|
+
contracts
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
var MAINNET = void 0;
|
|
36
|
+
var NETWORKS = {
|
|
37
|
+
testnet: TESTNET,
|
|
38
|
+
mainnet: MAINNET
|
|
39
|
+
};
|
|
40
|
+
function structScVal(fields) {
|
|
41
|
+
return stellarSdk.xdr.ScVal.scvMap(
|
|
42
|
+
Object.entries(fields).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0).map(
|
|
43
|
+
([key, val]) => new stellarSdk.xdr.ScMapEntry({
|
|
44
|
+
key: stellarSdk.xdr.ScVal.scvSymbol(key),
|
|
45
|
+
val
|
|
46
|
+
})
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/auth.ts
|
|
52
|
+
function buildInvocation(spec) {
|
|
53
|
+
const fn = new stellarSdk.xdr.InvokeContractArgs({
|
|
54
|
+
contractAddress: new stellarSdk.Address(spec.contractId).toScAddress(),
|
|
55
|
+
functionName: spec.functionName,
|
|
56
|
+
args: spec.args
|
|
57
|
+
});
|
|
58
|
+
const func = stellarSdk.xdr.SorobanAuthorizedFunction.sorobanAuthorizedFunctionTypeContractFn(fn);
|
|
59
|
+
return new stellarSdk.xdr.SorobanAuthorizedInvocation({
|
|
60
|
+
function: func,
|
|
61
|
+
subInvocations: spec.subInvocations ?? []
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function networkId(networkPassphrase) {
|
|
65
|
+
return stellarSdk.hash(Buffer.from(networkPassphrase));
|
|
66
|
+
}
|
|
67
|
+
function signaturePayload(invocation, nonce, signatureExpirationLedger, networkPassphrase) {
|
|
68
|
+
const preimage = stellarSdk.xdr.HashIdPreimage.envelopeTypeSorobanAuthorization(
|
|
69
|
+
new stellarSdk.xdr.HashIdPreimageSorobanAuthorization({
|
|
70
|
+
networkId: networkId(networkPassphrase),
|
|
71
|
+
nonce: stellarSdk.xdr.Int64.fromString(nonce.toString()),
|
|
72
|
+
signatureExpirationLedger,
|
|
73
|
+
invocation
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
return stellarSdk.hash(preimage.toXDR());
|
|
77
|
+
}
|
|
78
|
+
function randomNonce() {
|
|
79
|
+
const high = BigInt(Math.floor(Math.random() * 2 ** 30));
|
|
80
|
+
const low = BigInt(Math.floor(Math.random() * 2 ** 32));
|
|
81
|
+
return high << 32n | low;
|
|
82
|
+
}
|
|
83
|
+
async function buildClassicAuthEntry(address, invocation, sign, signatureExpirationLedger, networkPassphrase) {
|
|
84
|
+
const nonce = randomNonce();
|
|
85
|
+
const unsignedEntry = new stellarSdk.xdr.SorobanAuthorizationEntry({
|
|
86
|
+
credentials: stellarSdk.xdr.SorobanCredentials.sorobanCredentialsAddress(
|
|
87
|
+
new stellarSdk.xdr.SorobanAddressCredentials({
|
|
88
|
+
address: new stellarSdk.Address(address).toScAddress(),
|
|
89
|
+
nonce: stellarSdk.xdr.Int64.fromString(nonce.toString()),
|
|
90
|
+
signatureExpirationLedger,
|
|
91
|
+
signature: stellarSdk.xdr.ScVal.scvVoid()
|
|
92
|
+
})
|
|
93
|
+
),
|
|
94
|
+
rootInvocation: invocation
|
|
95
|
+
});
|
|
96
|
+
return stellarSdk.authorizeEntry(unsignedEntry, sign, signatureExpirationLedger, networkPassphrase);
|
|
97
|
+
}
|
|
98
|
+
function smartAccountAuthPayloadScVal(signerAddress, contextRuleIdsScVal) {
|
|
99
|
+
const signerKey = stellarSdk.xdr.ScVal.scvVec([
|
|
100
|
+
stellarSdk.xdr.ScVal.scvSymbol("Delegated"),
|
|
101
|
+
new stellarSdk.Address(signerAddress).toScVal()
|
|
102
|
+
]);
|
|
103
|
+
const signersMap = stellarSdk.xdr.ScVal.scvMap([
|
|
104
|
+
new stellarSdk.xdr.ScMapEntry({ key: signerKey, val: stellarSdk.xdr.ScVal.scvBytes(Buffer.alloc(0)) })
|
|
105
|
+
]);
|
|
106
|
+
return structScVal({
|
|
107
|
+
context_rule_ids: contextRuleIdsScVal,
|
|
108
|
+
signers: signersMap
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async function buildSmartAccountAuthEntries(opts) {
|
|
112
|
+
const contextRuleIds = opts.contextRuleIds ?? [0];
|
|
113
|
+
const nonceA = randomNonce();
|
|
114
|
+
const sigPayloadA = signaturePayload(
|
|
115
|
+
opts.rootInvocation,
|
|
116
|
+
nonceA,
|
|
117
|
+
opts.signatureExpirationLedger,
|
|
118
|
+
opts.networkPassphrase
|
|
119
|
+
);
|
|
120
|
+
const contextRuleIdsScVal = stellarSdk.xdr.ScVal.scvVec(
|
|
121
|
+
contextRuleIds.map((id) => stellarSdk.xdr.ScVal.scvU32(id))
|
|
122
|
+
);
|
|
123
|
+
const authDigest = stellarSdk.hash(
|
|
124
|
+
Buffer.concat([Buffer.from(sigPayloadA), Buffer.from(contextRuleIdsScVal.toXDR())])
|
|
125
|
+
);
|
|
126
|
+
const entryA = new stellarSdk.xdr.SorobanAuthorizationEntry({
|
|
127
|
+
credentials: stellarSdk.xdr.SorobanCredentials.sorobanCredentialsAddress(
|
|
128
|
+
new stellarSdk.xdr.SorobanAddressCredentials({
|
|
129
|
+
address: new stellarSdk.Address(opts.smartAccountId).toScAddress(),
|
|
130
|
+
nonce: stellarSdk.xdr.Int64.fromString(nonceA.toString()),
|
|
131
|
+
signatureExpirationLedger: opts.signatureExpirationLedger,
|
|
132
|
+
signature: smartAccountAuthPayloadScVal(opts.signerAddress, contextRuleIdsScVal)
|
|
133
|
+
})
|
|
134
|
+
),
|
|
135
|
+
rootInvocation: opts.rootInvocation
|
|
136
|
+
});
|
|
137
|
+
const nestedInvocation = buildInvocation({
|
|
138
|
+
contractId: opts.smartAccountId,
|
|
139
|
+
functionName: "__check_auth",
|
|
140
|
+
args: [stellarSdk.xdr.ScVal.scvBytes(authDigest)]
|
|
141
|
+
});
|
|
142
|
+
const entryB = await buildClassicAuthEntry(
|
|
143
|
+
opts.signerAddress,
|
|
144
|
+
nestedInvocation,
|
|
145
|
+
opts.sign,
|
|
146
|
+
opts.signatureExpirationLedger,
|
|
147
|
+
opts.networkPassphrase
|
|
148
|
+
);
|
|
149
|
+
return [entryA, entryB];
|
|
150
|
+
}
|
|
151
|
+
async function buildExecutorAuthEntry(opts) {
|
|
152
|
+
const invocation = buildInvocation({
|
|
153
|
+
contractId: opts.intentRegistryId,
|
|
154
|
+
functionName: "mark_child_executed",
|
|
155
|
+
args: [stellarSdk.xdr.ScVal.scvBytes(opts.intentId), stellarSdk.xdr.ScVal.scvU32(opts.childSequence)]
|
|
156
|
+
});
|
|
157
|
+
return buildClassicAuthEntry(
|
|
158
|
+
opts.executorAddress,
|
|
159
|
+
invocation,
|
|
160
|
+
opts.sign,
|
|
161
|
+
opts.signatureExpirationLedger,
|
|
162
|
+
opts.networkPassphrase
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
var DEFAULT_EXPIRATION_WINDOW_LEDGERS = 100;
|
|
166
|
+
var POLL_INTERVAL_MS = 3e3;
|
|
167
|
+
var MAX_POLL_ATTEMPTS = 40;
|
|
168
|
+
function addressScVal(id) {
|
|
169
|
+
return new stellarSdk.Address(id).toScVal();
|
|
170
|
+
}
|
|
171
|
+
function i128ScVal(value) {
|
|
172
|
+
return stellarSdk.nativeToScVal(value, { type: "i128" });
|
|
173
|
+
}
|
|
174
|
+
function u32ScVal(value) {
|
|
175
|
+
return stellarSdk.nativeToScVal(value, { type: "u32" });
|
|
176
|
+
}
|
|
177
|
+
function u64ScVal(value) {
|
|
178
|
+
return stellarSdk.nativeToScVal(value, { type: "u64" });
|
|
179
|
+
}
|
|
180
|
+
function boolScVal(value) {
|
|
181
|
+
return stellarSdk.nativeToScVal(value);
|
|
182
|
+
}
|
|
183
|
+
function bytesN32ScVal(value) {
|
|
184
|
+
if (value.length !== 32) {
|
|
185
|
+
throw new Error("Expected exactly 32 bytes.");
|
|
186
|
+
}
|
|
187
|
+
return stellarSdk.xdr.ScVal.scvBytes(value);
|
|
188
|
+
}
|
|
189
|
+
function buildAndPrepareTransaction(server, net, sourceAccount, contract, functionName, args, auth) {
|
|
190
|
+
const builder = new stellarSdk.TransactionBuilder(sourceAccount, {
|
|
191
|
+
fee: stellarSdk.BASE_FEE,
|
|
192
|
+
networkPassphrase: net.networkPassphrase
|
|
193
|
+
}).addOperation(stellarSdk.Operation.invokeContractFunction({ contract, function: functionName, args, auth })).setTimeout(120).build();
|
|
194
|
+
return server.prepareTransaction(builder);
|
|
195
|
+
}
|
|
196
|
+
async function prepareSmartAccountCall(opts, functionName, args) {
|
|
197
|
+
const server = new stellarSdk.rpc.Server(opts.net.rpcUrl);
|
|
198
|
+
const latestLedger = await server.getLatestLedger();
|
|
199
|
+
const signatureExpirationLedger = latestLedger.sequence + DEFAULT_EXPIRATION_WINDOW_LEDGERS;
|
|
200
|
+
const rootInvocation = buildInvocation({
|
|
201
|
+
contractId: opts.net.contracts.smartAccount,
|
|
202
|
+
functionName,
|
|
203
|
+
args
|
|
204
|
+
});
|
|
205
|
+
const [[entryA, entryB], sourceAccount] = await Promise.all([
|
|
206
|
+
buildSmartAccountAuthEntries({
|
|
207
|
+
smartAccountId: opts.net.contracts.smartAccount,
|
|
208
|
+
rootInvocation,
|
|
209
|
+
signerAddress: opts.signerAddress,
|
|
210
|
+
sign: opts.sign,
|
|
211
|
+
networkPassphrase: opts.net.networkPassphrase,
|
|
212
|
+
contextRuleIds: opts.contextRuleIds,
|
|
213
|
+
signatureExpirationLedger
|
|
214
|
+
}),
|
|
215
|
+
server.getAccount(opts.feeSourceAddress)
|
|
216
|
+
]);
|
|
217
|
+
return buildAndPrepareTransaction(
|
|
218
|
+
server,
|
|
219
|
+
opts.net,
|
|
220
|
+
sourceAccount,
|
|
221
|
+
opts.net.contracts.smartAccount,
|
|
222
|
+
functionName,
|
|
223
|
+
args,
|
|
224
|
+
[entryA, entryB]
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
async function prepareTransferPayment(opts, payment) {
|
|
228
|
+
const args = [
|
|
229
|
+
addressScVal(payment.asset),
|
|
230
|
+
addressScVal(payment.destination),
|
|
231
|
+
i128ScVal(payment.amount),
|
|
232
|
+
u64ScVal(payment.nonce),
|
|
233
|
+
u32ScVal(payment.expectedPolicyVersion)
|
|
234
|
+
];
|
|
235
|
+
return prepareSmartAccountCall(opts, "execute_transfer_payment", args);
|
|
236
|
+
}
|
|
237
|
+
async function prepareSplitPayment(opts, payment) {
|
|
238
|
+
const args = [
|
|
239
|
+
addressScVal(payment.asset),
|
|
240
|
+
stellarSdk.xdr.ScVal.scvVec(payment.recipients.map(addressScVal)),
|
|
241
|
+
stellarSdk.xdr.ScVal.scvVec(payment.amounts.map(i128ScVal)),
|
|
242
|
+
u64ScVal(payment.nonce),
|
|
243
|
+
u32ScVal(payment.expectedPolicyVersion)
|
|
244
|
+
];
|
|
245
|
+
return prepareSmartAccountCall(opts, "execute_split_payment", args);
|
|
246
|
+
}
|
|
247
|
+
function scheduledIntentScVal(intent) {
|
|
248
|
+
return structScVal({
|
|
249
|
+
intent_id: bytesN32ScVal(intent.intent_id),
|
|
250
|
+
asset: addressScVal(intent.asset),
|
|
251
|
+
destination: addressScVal(intent.destination),
|
|
252
|
+
amount: i128ScVal(intent.amount),
|
|
253
|
+
start_ledger: u32ScVal(intent.start_ledger),
|
|
254
|
+
end_ledger: u32ScVal(intent.end_ledger),
|
|
255
|
+
interval_ledgers: u32ScVal(intent.interval_ledgers),
|
|
256
|
+
max_executions: u32ScVal(intent.max_executions),
|
|
257
|
+
execution_count: u32ScVal(intent.execution_count),
|
|
258
|
+
policy_version: u32ScVal(intent.policy_version),
|
|
259
|
+
adapter: addressScVal(intent.adapter),
|
|
260
|
+
cancelled: boolScVal(intent.cancelled)
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
async function prepareScheduledPayment(opts, intent) {
|
|
264
|
+
const args = [scheduledIntentScVal(intent)];
|
|
265
|
+
return prepareSmartAccountCall(opts, "create_scheduled_payment", args);
|
|
266
|
+
}
|
|
267
|
+
async function prepareCancelScheduledPayment(opts, intentId) {
|
|
268
|
+
const args = [bytesN32ScVal(intentId)];
|
|
269
|
+
return prepareSmartAccountCall(opts, "cancel_scheduled_payment", args);
|
|
270
|
+
}
|
|
271
|
+
async function signAndSubmit(net, tx, feeSourceKeypair) {
|
|
272
|
+
const server = new stellarSdk.rpc.Server(net.rpcUrl);
|
|
273
|
+
tx.sign(feeSourceKeypair);
|
|
274
|
+
const sendResponse = await server.sendTransaction(tx);
|
|
275
|
+
if (sendResponse.status === "ERROR") {
|
|
276
|
+
throw new Error(`sendTransaction failed: ${JSON.stringify(sendResponse.errorResult)}`);
|
|
277
|
+
}
|
|
278
|
+
let response = await server.getTransaction(sendResponse.hash);
|
|
279
|
+
for (let attempt = 0; response.status === stellarSdk.rpc.Api.GetTransactionStatus.NOT_FOUND && attempt < MAX_POLL_ATTEMPTS; attempt++) {
|
|
280
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS));
|
|
281
|
+
response = await server.getTransaction(sendResponse.hash);
|
|
282
|
+
}
|
|
283
|
+
if (response.status === stellarSdk.rpc.Api.GetTransactionStatus.NOT_FOUND) {
|
|
284
|
+
throw new Error(
|
|
285
|
+
`transaction ${sendResponse.hash} not found after ${MAX_POLL_ATTEMPTS} polling attempts`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
if (response.status !== stellarSdk.rpc.Api.GetTransactionStatus.SUCCESS) {
|
|
289
|
+
throw new Error(`transaction ${sendResponse.hash} failed: ${JSON.stringify(response)}`);
|
|
290
|
+
}
|
|
291
|
+
return response;
|
|
292
|
+
}
|
|
293
|
+
async function prepareRelayerExecution(opts) {
|
|
294
|
+
const server = new stellarSdk.rpc.Server(opts.net.rpcUrl);
|
|
295
|
+
const latestLedger = await server.getLatestLedger();
|
|
296
|
+
const signatureExpirationLedger = latestLedger.sequence + DEFAULT_EXPIRATION_WINDOW_LEDGERS;
|
|
297
|
+
const [executorEntry, sourceAccount] = await Promise.all([
|
|
298
|
+
buildExecutorAuthEntry({
|
|
299
|
+
intentRegistryId: opts.net.contracts.intentRegistry,
|
|
300
|
+
intentId: opts.intentId,
|
|
301
|
+
childSequence: opts.childSequence,
|
|
302
|
+
executorAddress: opts.executorAddress,
|
|
303
|
+
sign: opts.sign,
|
|
304
|
+
networkPassphrase: opts.net.networkPassphrase,
|
|
305
|
+
signatureExpirationLedger
|
|
306
|
+
}),
|
|
307
|
+
server.getAccount(opts.executorAddress)
|
|
308
|
+
]);
|
|
309
|
+
const args = [bytesN32ScVal(opts.intentId), u32ScVal(opts.childSequence)];
|
|
310
|
+
return buildAndPrepareTransaction(
|
|
311
|
+
server,
|
|
312
|
+
opts.net,
|
|
313
|
+
sourceAccount,
|
|
314
|
+
opts.net.contracts.smartAccount,
|
|
315
|
+
"execute_scheduled_payment",
|
|
316
|
+
args,
|
|
317
|
+
[executorEntry]
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
function topicSymbol(event) {
|
|
321
|
+
const body = event.body().v0();
|
|
322
|
+
const first = body.topics()[0];
|
|
323
|
+
return first?.switch().name === "scvSymbol" ? first.sym().toString() : void 0;
|
|
324
|
+
}
|
|
325
|
+
var TOPIC_FIELDS = {
|
|
326
|
+
pay_ok: ["asset", "destination"],
|
|
327
|
+
splt_ok: ["asset"],
|
|
328
|
+
auto_ok: ["intent_id"],
|
|
329
|
+
pol_ok: ["operation"],
|
|
330
|
+
intent: ["intent_id"],
|
|
331
|
+
cancel: ["intent_id"],
|
|
332
|
+
exec: ["intent_id"],
|
|
333
|
+
open: ["request_id"],
|
|
334
|
+
appr: ["request_id", "guardian"],
|
|
335
|
+
final: ["request_id"],
|
|
336
|
+
recover: ["request_id"],
|
|
337
|
+
gfreeze: ["guardian"],
|
|
338
|
+
frozen: []
|
|
339
|
+
};
|
|
340
|
+
function decodeFields(event) {
|
|
341
|
+
const body = event.body().v0();
|
|
342
|
+
const topics = body.topics();
|
|
343
|
+
const topic = topicSymbol(event);
|
|
344
|
+
const topicFieldNames = topic && topic in TOPIC_FIELDS ? TOPIC_FIELDS[topic] : [];
|
|
345
|
+
const fromTopics = {};
|
|
346
|
+
topicFieldNames.forEach((name, i) => {
|
|
347
|
+
fromTopics[name] = stellarSdk.scValToNative(topics[i + 1]);
|
|
348
|
+
});
|
|
349
|
+
const native = stellarSdk.scValToNative(body.data());
|
|
350
|
+
const fromData = native && typeof native === "object" ? native : {};
|
|
351
|
+
return { ...fromTopics, ...fromData };
|
|
352
|
+
}
|
|
353
|
+
function parseContractEvent(event) {
|
|
354
|
+
const topic = topicSymbol(event);
|
|
355
|
+
const fields = decodeFields(event);
|
|
356
|
+
return { topic: topic ?? "", event: fields };
|
|
357
|
+
}
|
|
358
|
+
function parseContractEvents(events) {
|
|
359
|
+
return events.map(parseContractEvent);
|
|
360
|
+
}
|
|
361
|
+
function findEvent(events, topic) {
|
|
362
|
+
const found = events.find((e) => e.topic === topic);
|
|
363
|
+
return found?.event;
|
|
364
|
+
}
|
|
365
|
+
function isSimulationError(simulation) {
|
|
366
|
+
return "error" in simulation;
|
|
367
|
+
}
|
|
368
|
+
async function simulateRead(net, sourceAddress, contractId, method, args = []) {
|
|
369
|
+
const server = new stellarSdk.rpc.Server(net.rpcUrl);
|
|
370
|
+
const source = await server.getAccount(sourceAddress);
|
|
371
|
+
const tx = new stellarSdk.TransactionBuilder(source, { fee: stellarSdk.BASE_FEE, networkPassphrase: net.networkPassphrase }).addOperation(new stellarSdk.Contract(contractId).call(method, ...args)).setTimeout(60).build();
|
|
372
|
+
const simulation = await server.simulateTransaction(tx);
|
|
373
|
+
if (isSimulationError(simulation)) {
|
|
374
|
+
throw new Error(simulation.error);
|
|
375
|
+
}
|
|
376
|
+
return simulation.result?.retval ? stellarSdk.scValToNative(simulation.result.retval) : null;
|
|
377
|
+
}
|
|
378
|
+
function u32ScVal2(value) {
|
|
379
|
+
return stellarSdk.nativeToScVal(value, { type: "u32" });
|
|
380
|
+
}
|
|
381
|
+
function u64ScVal2(value) {
|
|
382
|
+
return stellarSdk.nativeToScVal(value, { type: "u64" });
|
|
383
|
+
}
|
|
384
|
+
function bytesN32ScVal2(value) {
|
|
385
|
+
if (value.length !== 32) {
|
|
386
|
+
throw new Error("Expected exactly 32 bytes.");
|
|
387
|
+
}
|
|
388
|
+
return stellarSdk.xdr.ScVal.scvBytes(value);
|
|
389
|
+
}
|
|
390
|
+
function addressScVal2(value) {
|
|
391
|
+
return stellarSdk.nativeToScVal(value, { type: "address" });
|
|
392
|
+
}
|
|
393
|
+
async function readAccountStatus(net, sourceAddress) {
|
|
394
|
+
return await simulateRead(net, sourceAddress, net.contracts.smartAccount, "status");
|
|
395
|
+
}
|
|
396
|
+
async function readOwner(net, sourceAddress) {
|
|
397
|
+
const result = await simulateRead(net, sourceAddress, net.contracts.smartAccount, "get_owner");
|
|
398
|
+
return typeof result === "string" ? result : null;
|
|
399
|
+
}
|
|
400
|
+
async function readContextRulesCount(net, sourceAddress) {
|
|
401
|
+
const result = await simulateRead(net, sourceAddress, net.contracts.smartAccount, "get_context_rules_count");
|
|
402
|
+
return Number(result ?? 0);
|
|
403
|
+
}
|
|
404
|
+
async function readContextRule(net, sourceAddress, contextRuleId) {
|
|
405
|
+
return await simulateRead(net, sourceAddress, net.contracts.smartAccount, "get_context_rule", [
|
|
406
|
+
u32ScVal2(contextRuleId)
|
|
407
|
+
]);
|
|
408
|
+
}
|
|
409
|
+
async function isNonceUsed(net, sourceAddress, nonce) {
|
|
410
|
+
const result = await simulateRead(net, sourceAddress, net.contracts.smartAccount, "is_nonce_used", [
|
|
411
|
+
u64ScVal2(nonce)
|
|
412
|
+
]);
|
|
413
|
+
return Boolean(result);
|
|
414
|
+
}
|
|
415
|
+
async function readPolicyVersion(net, sourceAddress) {
|
|
416
|
+
const result = await simulateRead(net, sourceAddress, net.contracts.policyEngine, "version");
|
|
417
|
+
return Number(result ?? 1);
|
|
418
|
+
}
|
|
419
|
+
async function readScheduledIntent(net, sourceAddress, intentId) {
|
|
420
|
+
return await simulateRead(net, sourceAddress, net.contracts.intentRegistry, "get_intent", [
|
|
421
|
+
bytesN32ScVal2(intentId)
|
|
422
|
+
]);
|
|
423
|
+
}
|
|
424
|
+
async function isChildExecuted(net, sourceAddress, intentId, childSequence) {
|
|
425
|
+
const result = await simulateRead(net, sourceAddress, net.contracts.intentRegistry, "is_child_executed", [
|
|
426
|
+
bytesN32ScVal2(intentId),
|
|
427
|
+
u32ScVal2(childSequence)
|
|
428
|
+
]);
|
|
429
|
+
return Boolean(result);
|
|
430
|
+
}
|
|
431
|
+
async function readRecoveryRequest(net, sourceAddress, requestId) {
|
|
432
|
+
return await simulateRead(net, sourceAddress, net.contracts.recoveryManager, "request_status", [
|
|
433
|
+
bytesN32ScVal2(requestId)
|
|
434
|
+
]);
|
|
435
|
+
}
|
|
436
|
+
async function readLiveApprovalCount(net, sourceAddress, requestId) {
|
|
437
|
+
const result = await simulateRead(net, sourceAddress, net.contracts.recoveryManager, "live_approval_count", [
|
|
438
|
+
bytesN32ScVal2(requestId)
|
|
439
|
+
]);
|
|
440
|
+
return Number(result ?? 0);
|
|
441
|
+
}
|
|
442
|
+
async function isGuardian(net, sourceAddress, guardian) {
|
|
443
|
+
const result = await simulateRead(net, sourceAddress, net.contracts.recoveryManager, "is_guardian", [
|
|
444
|
+
addressScVal2(guardian)
|
|
445
|
+
]);
|
|
446
|
+
return Boolean(result);
|
|
447
|
+
}
|
|
448
|
+
async function readGuardianFreezeEpoch(net, sourceAddress) {
|
|
449
|
+
const result = await simulateRead(net, sourceAddress, net.contracts.recoveryManager, "guardian_freeze_epoch");
|
|
450
|
+
return Number(result ?? 0);
|
|
451
|
+
}
|
|
452
|
+
async function readFactoryWasmHashes(net, sourceAddress) {
|
|
453
|
+
return await simulateRead(
|
|
454
|
+
net,
|
|
455
|
+
sourceAddress,
|
|
456
|
+
net.contracts.accountFactory,
|
|
457
|
+
"get_wasm_hashes"
|
|
458
|
+
);
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
Object.defineProperty(exports, "Account", {
|
|
462
|
+
enumerable: true,
|
|
463
|
+
get: function () { return stellarSdk.Account; }
|
|
464
|
+
});
|
|
465
|
+
exports.MAINNET = MAINNET;
|
|
466
|
+
exports.MAINNET_NETWORK_PASSPHRASE = MAINNET_NETWORK_PASSPHRASE;
|
|
467
|
+
exports.MAINNET_RPC_URL_ENV = MAINNET_RPC_URL_ENV;
|
|
468
|
+
exports.NETWORKS = NETWORKS;
|
|
469
|
+
exports.TESTNET = TESTNET;
|
|
470
|
+
exports.buildExecutorAuthEntry = buildExecutorAuthEntry;
|
|
471
|
+
exports.buildInvocation = buildInvocation;
|
|
472
|
+
exports.buildMainnetConfig = buildMainnetConfig;
|
|
473
|
+
exports.buildSmartAccountAuthEntries = buildSmartAccountAuthEntries;
|
|
474
|
+
exports.findEvent = findEvent;
|
|
475
|
+
exports.isChildExecuted = isChildExecuted;
|
|
476
|
+
exports.isGuardian = isGuardian;
|
|
477
|
+
exports.isNonceUsed = isNonceUsed;
|
|
478
|
+
exports.parseContractEvent = parseContractEvent;
|
|
479
|
+
exports.parseContractEvents = parseContractEvents;
|
|
480
|
+
exports.prepareCancelScheduledPayment = prepareCancelScheduledPayment;
|
|
481
|
+
exports.prepareRelayerExecution = prepareRelayerExecution;
|
|
482
|
+
exports.prepareScheduledPayment = prepareScheduledPayment;
|
|
483
|
+
exports.prepareSplitPayment = prepareSplitPayment;
|
|
484
|
+
exports.prepareTransferPayment = prepareTransferPayment;
|
|
485
|
+
exports.readAccountStatus = readAccountStatus;
|
|
486
|
+
exports.readContextRule = readContextRule;
|
|
487
|
+
exports.readContextRulesCount = readContextRulesCount;
|
|
488
|
+
exports.readFactoryWasmHashes = readFactoryWasmHashes;
|
|
489
|
+
exports.readGuardianFreezeEpoch = readGuardianFreezeEpoch;
|
|
490
|
+
exports.readLiveApprovalCount = readLiveApprovalCount;
|
|
491
|
+
exports.readOwner = readOwner;
|
|
492
|
+
exports.readPolicyVersion = readPolicyVersion;
|
|
493
|
+
exports.readRecoveryRequest = readRecoveryRequest;
|
|
494
|
+
exports.readScheduledIntent = readScheduledIntent;
|
|
495
|
+
exports.signAndSubmit = signAndSubmit;
|
|
496
|
+
exports.signaturePayload = signaturePayload;
|
|
497
|
+
//# sourceMappingURL=index.cjs.map
|
|
498
|
+
//# sourceMappingURL=index.cjs.map
|