@atumlabs/mppx-atum-escrow 0.3.0 → 0.4.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/CHANGELOG.md +42 -0
- package/LICENSE +201 -165
- package/NOTICE +2 -0
- package/README.md +88 -11
- package/THIRD-PARTY-NOTICES.txt +23 -29
- package/dist/{chunk-4YD6566T.js → chunk-EWIOTGMO.js} +18 -8
- package/dist/{chunk-ZFA5SSUP.js → chunk-IGTT7XSG.js} +7329 -2023
- package/dist/{chunk-Z3AUNEU5.js → chunk-LAWFMGYD.js} +1333 -271
- package/dist/client.d.ts +181 -42
- package/dist/client.js +11 -8
- package/dist/index.d.ts +4 -77
- package/dist/index.js +12 -9
- package/dist/{internal-9tB7y-A7.d.ts → internal-BZBJJfaL.d.ts} +105 -42
- package/dist/server.d.ts +47 -43
- package/dist/server.js +4 -6
- package/package.json +14 -11
package/README.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
# @atumlabs/mppx-atum-escrow
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Copyright 2026 Atum Labs, Inc.
|
|
4
4
|
>
|
|
5
|
-
>
|
|
5
|
+
> Licensed under the Apache License, Version 2.0. See the `LICENSE` file
|
|
6
|
+
> distributed with this package.
|
|
6
7
|
|
|
7
8
|
An [`mppx`](https://www.npmjs.com/package/mppx) payment method that lets a merchant accept
|
|
8
9
|
**cross-chain stablecoin payments** through Atum, over the Machine Payments Protocol (MPP).
|
|
10
|
+
Full documentation: [docs.atum.xyz](https://docs.atum.xyz).
|
|
9
11
|
|
|
10
12
|
- The **payer** funds the payment in any supported source asset and chain (e.g. USDC on Base,
|
|
11
13
|
USDT on Tron, or USDC on Solana).
|
|
@@ -81,9 +83,6 @@ The merchant examples below also use
|
|
|
81
83
|
[`@atumlabs/payment-gateway-client`](https://www.npmjs.com/package/@atumlabs/payment-gateway-client)
|
|
82
84
|
for the gateway connection and corridor defaults.
|
|
83
85
|
|
|
84
|
-
> The snippets below are illustrative. For complete, runnable, end-to-end integrations
|
|
85
|
-
> (payer + merchant), see the examples repository: **https://github.com/Atum-Labs/examples**.
|
|
86
|
-
|
|
87
86
|
## Key concepts
|
|
88
87
|
|
|
89
88
|
| Term | What it means |
|
|
@@ -101,6 +100,18 @@ for the gateway connection and corridor defaults.
|
|
|
101
100
|
All addresses and amounts are strings; all amounts are **atomic units** (never floats). Addresses
|
|
102
101
|
are in each chain's native form — `0x…` hex for EVM, base58 for Tron and Solana.
|
|
103
102
|
|
|
103
|
+
### Which chains and assets can a corridor use?
|
|
104
|
+
|
|
105
|
+
Atum supports many corridors. The identifier for every supported token is listed under
|
|
106
|
+
[supported assets](https://docs.atum.xyz/get-started/reference/supported-assets), and the chain ids
|
|
107
|
+
under [supported networks](https://docs.atum.xyz/get-started/reference/supported-networks). Assets
|
|
108
|
+
are named with [CAIP-19](https://chainagnostic.org/CAIPs/caip-19) identifiers, for example
|
|
109
|
+
`eip155:84532/erc20:0x036CbD53842c5426634e7929541eC2318f3dCF7e` for USDC on Base Sepolia.
|
|
110
|
+
|
|
111
|
+
Copy identifiers exactly: base58 values, such as Solana token mints and account addresses, are
|
|
112
|
+
case-sensitive. The escrow and role addresses for each chain are filled in by
|
|
113
|
+
`corridorFromDefaults`, so you never paste those by hand.
|
|
114
|
+
|
|
104
115
|
## Quick start — merchant (server)
|
|
105
116
|
|
|
106
117
|
```ts
|
|
@@ -231,11 +242,66 @@ await ensureSourceApproval({
|
|
|
231
242
|
owner: wallet.address,
|
|
232
243
|
signer: wallet,
|
|
233
244
|
// Pass the source cap this charge needs (from the challenge). A leftover smaller allowance
|
|
234
|
-
// then won't be mistaken for enough.
|
|
245
|
+
// then won't be mistaken for enough.
|
|
235
246
|
requiredAllowance: BigInt(challenge.request.source.amount),
|
|
236
247
|
});
|
|
237
248
|
```
|
|
238
249
|
|
|
250
|
+
Paying from Tron takes a TronWeb instance instead of an ethers signer; everything else is the
|
|
251
|
+
same, and the Permit2 address for the network is resolved for you:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
await ensureSourceApproval({ network: "tron:mainnet", token, owner, tronWeb });
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The approval waits to be mined before returning, bounded by `confirmation.timeoutMs` (one minute
|
|
258
|
+
by default); a timeout is reported as unconfirmed rather than failed, since the transaction may
|
|
259
|
+
still land. `onSubmitted` hands you the hash the moment it is broadcast.
|
|
260
|
+
|
|
261
|
+
`isUnconfirmed(error)` tells the two apart. It matters because the responses are opposite: a
|
|
262
|
+
failed approval needs another one, an unconfirmed approval needs a look at the transaction and
|
|
263
|
+
nothing else. Sending a second one on top of the first only pays for an allowance you are already
|
|
264
|
+
getting.
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
try {
|
|
268
|
+
await ensureSourceApproval({ network, token, owner, signer });
|
|
269
|
+
} catch (error) {
|
|
270
|
+
if (isUnconfirmed(error)) {
|
|
271
|
+
// Broadcast, not yet seen to confirm. Check the hash from onSubmitted; do not re-send.
|
|
272
|
+
} else {
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
On EVM, tokens that refuse to overwrite a non-zero allowance — mainnet USDT most notably — are
|
|
279
|
+
reset to zero first, automatically and only where the token demands it; the result then carries a
|
|
280
|
+
`resetTxHash` too. Tron does not do this, because an ordinary TRC-20 accepts the change in place.
|
|
281
|
+
|
|
282
|
+
The approval sent is unlimited, so later charges on the same token need no further transaction.
|
|
283
|
+
To bound the approval that gets sent, pass `approvalAmount`. On its own the amount is treated as
|
|
284
|
+
its own requirement, so an allowance still holding the full bound is left alone rather than
|
|
285
|
+
re-approved — the right answer for a one-off approval. Across repeated payments, pair it with
|
|
286
|
+
`requiredAllowance`: Permit2 decrements the allowance on every payment, so a bound measured
|
|
287
|
+
against itself stops covering itself the moment the first charge lands, and every later call
|
|
288
|
+
would send another approval. Either way a bounded approval is consumed as it is spent and
|
|
289
|
+
eventually has to be granted again.
|
|
290
|
+
|
|
291
|
+
These helpers raise an allowance to what a payment needs; they never lower one. A wallet already
|
|
292
|
+
holding more than `approvalAmount` is left exactly as it is and reports `alreadySufficient`
|
|
293
|
+
without sending anything. Reducing or revoking an allowance is a separate operation, and not one
|
|
294
|
+
these perform.
|
|
295
|
+
|
|
296
|
+
`needsSourceApproval(params)` takes the same arguments and answers the same question without
|
|
297
|
+
sending anything, so it is safe to call before every charge:
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
if (await needsSourceApproval({ network, token, owner, signer })) {
|
|
301
|
+
// tell the payer a one-off approval transaction is coming, before asking them to sign
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
239
305
|
## What the merchant `verify()` guarantees
|
|
240
306
|
|
|
241
307
|
`verify()` fails fast (no chain I/O) before submitting, and throws if any check fails. The Atum
|
|
@@ -274,6 +340,9 @@ On success you get an `AtumEscrowReceipt` — the MPP receipt plus the full sett
|
|
|
274
340
|
}
|
|
275
341
|
```
|
|
276
342
|
|
|
343
|
+
`verify()` resolves with this type, so `fulfillmentConfirmation` is available straight off the
|
|
344
|
+
result. `AtumEscrowReceipt` is exported, so you can name it in your own function signatures.
|
|
345
|
+
|
|
277
346
|
## Retries and idempotency
|
|
278
347
|
|
|
279
348
|
A retry must never become a second charge, and two different purchases must never collapse into
|
|
@@ -465,7 +534,7 @@ Import everything from the root, or from the role-specific entry points (which e
|
|
|
465
534
|
each side needs):
|
|
466
535
|
|
|
467
536
|
- `@atumlabs/mppx-atum-escrow` — everything below
|
|
468
|
-
- `@atumlabs/mppx-atum-escrow/client` — `registerClient`, `ensureSourceApproval` + payer types
|
|
537
|
+
- `@atumlabs/mppx-atum-escrow/client` — `registerClient`, `ensureSourceApproval`, `needsSourceApproval` + payer types
|
|
469
538
|
- `@atumlabs/mppx-atum-escrow/server` — `registerServer`, `buildChargeChallenge`,
|
|
470
539
|
`buildChargeRequest`, `validateCorridor`, `corridorFromDefaults`, the settlement errors +
|
|
471
540
|
merchant types
|
|
@@ -473,12 +542,13 @@ each side needs):
|
|
|
473
542
|
| Export | Description |
|
|
474
543
|
| --- | --- |
|
|
475
544
|
| `registerClient(config)` | Payer-side method. `config`: `{ signer, account, now?, solanaClockReader? }`. |
|
|
476
|
-
| `registerServer(config)` | Merchant-side method. `config`: `{ submitter, now? }`. |
|
|
545
|
+
| `registerServer(config)` | Merchant-side method. `config`: `{ submitter, now? }`. Returns an `AtumEscrowServer`, whose `verify()` resolves with an `AtumEscrowReceipt`. |
|
|
477
546
|
| `buildChargeChallenge(corridor, select, fulfillmentAmount, { intentId, issuedAt? })` | Builds a `charge` challenge — the payment terms plus the per-purchase identifier that makes a retry safe. **Use this.** Returns `{ request, meta }`. |
|
|
478
547
|
| `buildChargeRequest(corridor, select, fulfillmentAmount, options?)` | The payment terms alone, without the identifier. For supplying challenge metadata by hand. |
|
|
479
548
|
| `validateCorridor(corridor)` | Validates a corridor's shape and per-source addresses (run automatically by both builders). |
|
|
480
549
|
| `corridorFromDefaults(defaults, params)` | Builds a corridor by fetching escrow/role/proxy addresses from the gateway `/defaults`. |
|
|
481
|
-
| `ensureSourceApproval(params)` | Ensures the payer has approved Permit2 to move the source token
|
|
550
|
+
| `ensureSourceApproval(params)` | Ensures the payer has approved Permit2 to move the source token. `signer` for EVM, `tronWeb` for Tron; no-op on Solana. |
|
|
551
|
+
| `needsSourceApproval(params)` | Whether `ensureSourceApproval` would send a transaction. Read-only, spends no gas. |
|
|
482
552
|
| `SettlementPendingError`, `SettlementFailedError`, `PaymentRejectedError` | The non-receipt outcomes of `verify()`. See [Settlement outcomes](#settlement-outcomes). |
|
|
483
553
|
| `isSettlementPending`, `isSettlementFailed`, `isPaymentRejected` | Guards for the above. |
|
|
484
554
|
| `atumEscrowChargeMethod` | The base `mppx` method (advanced/custom wiring). |
|
|
@@ -488,10 +558,17 @@ each side needs):
|
|
|
488
558
|
|
|
489
559
|
Key types: `AtumEscrowCorridor`, `AtumEscrowSource`, `SenderSigner`, `SenderSignerOptions`,
|
|
490
560
|
`PaymentSubmitter`, `PaymentSubmitResult`, `PaymentSettlementStatus`, `AtumEscrowClientConfig`,
|
|
491
|
-
`AtumEscrowServerConfig`, `ChainDefaultsSource`, `EnsureApprovalResult`,
|
|
492
|
-
`AtumEscrowCredential`, `AtumEscrowReceipt`, `ChargeChallenge`, `ChargeRequest`,
|
|
561
|
+
`AtumEscrowServer`, `AtumEscrowServerConfig`, `ChainDefaultsSource`, `EnsureApprovalResult`,
|
|
562
|
+
`AtumEscrowChallenge`, `AtumEscrowCredential`, `AtumEscrowReceipt`, `ChargeChallenge`, `ChargeRequest`,
|
|
493
563
|
`SettlementErrorDetails`, `PaymentRequest`, `FulfillmentConfirmation`.
|
|
494
564
|
|
|
495
565
|
> **EVM implementation note:** on EVM the deposit authorization is a Permit2
|
|
496
566
|
> `PermitWitnessTransferFrom` signature; Tron uses the equivalent TIP-712 typed data, and Solana
|
|
497
567
|
> uses an ed25519-signed deposit. The public API is the same across all three.
|
|
568
|
+
|
|
569
|
+
## Further reading
|
|
570
|
+
|
|
571
|
+
- [Accepting and making MPP payments with Atum](https://docs.atum.xyz/payment-protocols/mpp/overview)
|
|
572
|
+
- [Supported assets](https://docs.atum.xyz/get-started/reference/supported-assets) and [supported networks](https://docs.atum.xyz/get-started/reference/supported-networks)
|
|
573
|
+
- [MPP](https://mpp.dev)
|
|
574
|
+
- [Atum documentation](https://docs.atum.xyz)
|
package/THIRD-PARTY-NOTICES.txt
CHANGED
|
@@ -2,6 +2,12 @@ THIRD-PARTY SOFTWARE NOTICES AND INFORMATION
|
|
|
2
2
|
==============================================================================
|
|
3
3
|
@atumlabs/mppx-atum-escrow
|
|
4
4
|
|
|
5
|
+
@atumlabs/mppx-atum-escrow is licensed under the Apache License, Version 2.0, as stated
|
|
6
|
+
in the package-root LICENSE file. THIS file is not that license. This
|
|
7
|
+
package includes the third-party software identified below; the licenses and
|
|
8
|
+
notices reproduced here apply only to those third-party components. They do not
|
|
9
|
+
modify the Apache-2.0 license governing this package or any Atum-authored code.
|
|
10
|
+
|
|
5
11
|
The published artifact of this package (the compiled code under dist/) statically
|
|
6
12
|
bundles the third-party open-source components listed below; their source is
|
|
7
13
|
redistributed within this package, so their license and copyright notices are
|
|
@@ -11,9 +17,9 @@ as (peer)dependencies of this package (for example @solana/web3.js, ethers, bs58
|
|
|
11
17
|
tweetnacl, zod, and mppx) — those ship under their own licenses and are not
|
|
12
18
|
redistributed here.
|
|
13
19
|
|
|
14
|
-
LICENSE SUMMARY (
|
|
20
|
+
LICENSE SUMMARY (28 components)
|
|
15
21
|
------------------------------------------------------------------------------
|
|
16
|
-
|
|
22
|
+
28 MIT
|
|
17
23
|
==============================================================================
|
|
18
24
|
|
|
19
25
|
------------------------------------------------------------------------------
|
|
@@ -43,6 +49,13 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
43
49
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
44
50
|
THE SOFTWARE.
|
|
45
51
|
|
|
52
|
+
------------------------------------------------------------------------------
|
|
53
|
+
agent-base 6.0.2 (MIT)
|
|
54
|
+
Author: Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)
|
|
55
|
+
------------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
[No license file is distributed inside this package. Declared license: MIT; author: Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/).]
|
|
58
|
+
|
|
46
59
|
------------------------------------------------------------------------------
|
|
47
60
|
asynckit 0.4.0 (MIT)
|
|
48
61
|
Author: Alex Indigo <iam@alexindigo.com>
|
|
@@ -71,7 +84,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
71
84
|
SOFTWARE.
|
|
72
85
|
|
|
73
86
|
------------------------------------------------------------------------------
|
|
74
|
-
axios 1.
|
|
87
|
+
axios 1.20.0 (MIT)
|
|
75
88
|
Author: Matt Zabriskie
|
|
76
89
|
------------------------------------------------------------------------------
|
|
77
90
|
|
|
@@ -556,6 +569,13 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
556
569
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
557
570
|
SOFTWARE.
|
|
558
571
|
|
|
572
|
+
------------------------------------------------------------------------------
|
|
573
|
+
https-proxy-agent 5.0.1 (MIT)
|
|
574
|
+
Author: Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/)
|
|
575
|
+
------------------------------------------------------------------------------
|
|
576
|
+
|
|
577
|
+
[No license file is distributed inside this package. Declared license: MIT; author: Nathan Rajlich <nathan@tootallnate.net> (http://n8.io/).]
|
|
578
|
+
|
|
559
579
|
------------------------------------------------------------------------------
|
|
560
580
|
math-intrinsics 1.1.0 (MIT)
|
|
561
581
|
Author: Jordan Harband <ljharb@gmail.com>
|
|
@@ -665,32 +685,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
665
685
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
666
686
|
SOFTWARE.
|
|
667
687
|
|
|
668
|
-
------------------------------------------------------------------------------
|
|
669
|
-
proxy-from-env 1.1.0 (MIT)
|
|
670
|
-
Author: Rob Wu <rob@robwu.nl> (https://robwu.nl/)
|
|
671
|
-
------------------------------------------------------------------------------
|
|
672
|
-
|
|
673
|
-
The MIT License
|
|
674
|
-
|
|
675
|
-
Copyright (C) 2016-2018 Rob Wu <rob@robwu.nl>
|
|
676
|
-
|
|
677
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
678
|
-
this software and associated documentation files (the "Software"), to deal in
|
|
679
|
-
the Software without restriction, including without limitation the rights to
|
|
680
|
-
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
681
|
-
of the Software, and to permit persons to whom the Software is furnished to do
|
|
682
|
-
so, subject to the following conditions:
|
|
683
|
-
|
|
684
|
-
The above copyright notice and this permission notice shall be included in all
|
|
685
|
-
copies or substantial portions of the Software.
|
|
686
|
-
|
|
687
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
688
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
689
|
-
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
690
|
-
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
691
|
-
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
692
|
-
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
693
|
-
|
|
694
688
|
------------------------------------------------------------------------------
|
|
695
689
|
supports-color 10.2.2 (MIT)
|
|
696
690
|
Author: Sindre Sorhus <sindresorhus@gmail.com>
|
|
@@ -11,8 +11,9 @@ import {
|
|
|
11
11
|
intentIdOf,
|
|
12
12
|
namespaceOf,
|
|
13
13
|
require_dist2 as require_dist,
|
|
14
|
-
sameAddress
|
|
15
|
-
|
|
14
|
+
sameAddress,
|
|
15
|
+
sameAssetIdentifier
|
|
16
|
+
} from "./chunk-LAWFMGYD.js";
|
|
16
17
|
|
|
17
18
|
// src/server.ts
|
|
18
19
|
var import_payment_request_sender_auth2 = __toESM(require_dist(), 1);
|
|
@@ -156,8 +157,7 @@ function registerServer(config) {
|
|
|
156
157
|
throw new Error("atum-escrow: destination account does not match the challenge");
|
|
157
158
|
}
|
|
158
159
|
const expectedDestAsset = assetIdentifier(extra.destination.network, extra.destination.asset);
|
|
159
|
-
|
|
160
|
-
if (!destAssetMatches) {
|
|
160
|
+
if (!sameAssetIdentifier(dest.asset_identifier, expectedDestAsset)) {
|
|
161
161
|
throw new Error("atum-escrow: destination asset does not match the challenge");
|
|
162
162
|
}
|
|
163
163
|
if (pr.fulfillment_amount !== extra.fulfillmentAmount) {
|
|
@@ -179,7 +179,9 @@ function registerServer(config) {
|
|
|
179
179
|
throw new Error("atum-escrow: fulfillment_proxy does not match the challenge");
|
|
180
180
|
}
|
|
181
181
|
if (!sameAddress(pr.fulfillment_verifier?.account ?? "", expectedVerifier.account)) {
|
|
182
|
-
throw new Error(
|
|
182
|
+
throw new Error(
|
|
183
|
+
"atum-escrow: fulfillment_verifier.account does not match the challenge releaser"
|
|
184
|
+
);
|
|
183
185
|
}
|
|
184
186
|
if ((pr.fulfillment_verifier?.endpoint ?? "") !== expectedVerifier.endpoint) {
|
|
185
187
|
throw new Error("atum-escrow: fulfillment_verifier.endpoint does not match the challenge");
|
|
@@ -209,7 +211,7 @@ function registerServer(config) {
|
|
|
209
211
|
const result = await config.submitter.submit(pr);
|
|
210
212
|
const fc = result.fulfillment_confirmation;
|
|
211
213
|
if (!fc) {
|
|
212
|
-
const terminal = result.status === "failed"
|
|
214
|
+
const terminal = result.status === "failed";
|
|
213
215
|
if (terminal) {
|
|
214
216
|
throw new SettlementFailedError({ paymentId: result.payment_id, state: result.status });
|
|
215
217
|
}
|
|
@@ -247,13 +249,21 @@ function validateCorridor(corridor) {
|
|
|
247
249
|
throw new Error("atum-escrow: corridor must configure at least one source");
|
|
248
250
|
}
|
|
249
251
|
for (const src of corridor.sources) {
|
|
250
|
-
for (const field of [
|
|
252
|
+
for (const field of [
|
|
253
|
+
"network",
|
|
254
|
+
"escrow",
|
|
255
|
+
"reserver",
|
|
256
|
+
"releaser",
|
|
257
|
+
"fulfillmentVerifierEndpoint"
|
|
258
|
+
]) {
|
|
251
259
|
if (!src[field]) {
|
|
252
260
|
throw new Error(`atum-escrow: source ${src.network ?? "?"} is missing '${field}'`);
|
|
253
261
|
}
|
|
254
262
|
}
|
|
255
263
|
if (!src.assets || src.assets.length === 0 || src.assets.some((a) => !a)) {
|
|
256
|
-
throw new Error(
|
|
264
|
+
throw new Error(
|
|
265
|
+
`atum-escrow: source ${src.network} must list at least one non-empty asset in 'assets'`
|
|
266
|
+
);
|
|
257
267
|
}
|
|
258
268
|
if (namespaceOf(src.network) === "tron") {
|
|
259
269
|
(0, import_payment_request_sender_auth.resolveTronPermit2)(src.network);
|