@defuse-protocol/intents-sdk 0.14.0 → 0.15.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/README.md +452 -345
- package/dist/index.cjs +381 -65
- package/dist/index.d.cts +16 -10
- package/dist/index.d.ts +16 -10
- package/dist/index.js +385 -54
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,214 +1,306 @@
|
|
|
1
1
|
# @defuse-protocol/intents-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A comprehensive SDK for Near Intents protocol. This SDK provides tools for intent execution, deposits, withdrawals, and
|
|
4
|
+
interacting with various bridge implementations across multiple blockchains.
|
|
5
|
+
|
|
6
|
+
## Table of Contents
|
|
7
|
+
|
|
8
|
+
- [Installation](#installation)
|
|
9
|
+
- [Features](#features)
|
|
10
|
+
- [Quick Start](#quick-start)
|
|
11
|
+
- [Core Functionalities](#core-functionalities)
|
|
12
|
+
- [Core Concepts](#core-concepts)
|
|
13
|
+
- [Intent Execution](#intent-execution)
|
|
14
|
+
- [Deposits](#deposits)
|
|
15
|
+
- [Withdrawals](#withdrawals)
|
|
16
|
+
- [Routes and Bridges](#routes-and-bridges)
|
|
17
|
+
- [Route Types](#route-types)
|
|
18
|
+
- [Fee Estimation](#fee-estimation)
|
|
19
|
+
- [Advanced Usage](#advanced-usage)
|
|
20
|
+
- [Custom RPC URLs](#custom-rpc-urls)
|
|
21
|
+
- [Other Intent Signers](#other-intent-signers)
|
|
22
|
+
- [Intent Publishing Hooks](#intent-publishing-hooks)
|
|
23
|
+
- [Batch Withdrawals](#batch-withdrawals)
|
|
24
|
+
- [Intent Management](#intent-management)
|
|
25
|
+
- [Configure Withdrawal Routes](#configure-withdrawal-routes)
|
|
26
|
+
- [Asset Information Parsing](#asset-information-parsing)
|
|
27
|
+
- [Waiting for Completion](#waiting-for-completion)
|
|
28
|
+
- [Error Handling](#error-handling)
|
|
29
|
+
- [Supported Networks](#supported-networks)
|
|
30
|
+
- [Development](#development)
|
|
4
31
|
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Bridging from Near Intents:
|
|
8
|
-
- Support for multiple bridge implementations (Hot, PoA)
|
|
9
|
-
- Single and batch withdrawal operations
|
|
10
|
-
- Automatic fee estimation
|
|
11
|
-
- Built-in validation for withdrawal constraints:
|
|
12
|
-
- PoA Bridge minimum withdrawal amounts
|
|
13
|
-
- Hot Bridge Stellar trustline validation
|
|
14
|
-
- Transfers within Near Intents
|
|
15
|
-
- Transfers to NEAR blockchain
|
|
16
|
-
- Transfers to Virtual Chains (e.g. Aurora)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Note: Bridging to Near Intents is not supported yet.
|
|
21
|
-
|
|
22
32
|
## Installation
|
|
23
33
|
|
|
24
34
|
```bash
|
|
25
35
|
npm install @defuse-protocol/intents-sdk --save-exact
|
|
26
36
|
```
|
|
27
37
|
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
| Feature | Status | Description |
|
|
41
|
+
|------------------|:------:|------------------------------------------------------------------------|
|
|
42
|
+
| Intent Execution | ✅ | Sign, submit, and track intent execution on Near Intents |
|
|
43
|
+
| Deposits | ❌ | Deposit funds to Near Intents (use bridge interfaces directly) |
|
|
44
|
+
| Withdrawals | ✅ | Complete withdrawal functionality from Near Intents to external chains |
|
|
45
|
+
|
|
28
46
|
## Quick Start
|
|
29
47
|
|
|
48
|
+
### Basic Setup
|
|
49
|
+
|
|
50
|
+
First, initialize the SDK with your referral code and intent signer:
|
|
51
|
+
|
|
30
52
|
```typescript
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
53
|
+
import {IntentsSDK, createIntentSignerNearKeyPair} from '@defuse-protocol/intents-sdk';
|
|
54
|
+
import {KeyPair} from 'near-api-js';
|
|
33
55
|
|
|
34
|
-
// Initialize the SDK
|
|
56
|
+
// Initialize the SDK
|
|
35
57
|
const sdk = new IntentsSDK({
|
|
36
58
|
referral: 'your-referral-code', // Only referral is required
|
|
59
|
+
intentSigner: createIntentSignerNearKeyPair({
|
|
60
|
+
keypair: KeyPair.fromString('your-private-key'),
|
|
61
|
+
accountId: 'your-account.near'
|
|
62
|
+
})
|
|
37
63
|
});
|
|
64
|
+
```
|
|
38
65
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
accountId: 'your-account.near'
|
|
44
|
-
});
|
|
45
|
-
sdk.setIntentSigner(signer);
|
|
66
|
+
### Most Common Use Case: Withdrawals
|
|
67
|
+
|
|
68
|
+
For most users, the primary use case is withdrawing funds from Near Intents to external chains. Use the high-level
|
|
69
|
+
`processWithdrawal` method:
|
|
46
70
|
|
|
47
|
-
|
|
71
|
+
```typescript
|
|
72
|
+
// Complete end-to-end withdrawal (recommended)
|
|
48
73
|
const result = await sdk.processWithdrawal({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
74
|
+
withdrawalParams: {
|
|
75
|
+
assetId: 'nep141:usdt.tether-token.near', // USDT token on NEAR
|
|
76
|
+
amount: 1000000n, // 1 USDT (in smallest units - 6 decimals)
|
|
77
|
+
destinationAddress: '0x742d35Cc6634C0532925a3b8D84B2021F90a51A3', // Ethereum address
|
|
78
|
+
feeInclusive: false, // Amount excludes withdrawal fees
|
|
79
|
+
}
|
|
56
80
|
});
|
|
57
81
|
|
|
58
82
|
console.log('Intent hash:', result.intentHash);
|
|
59
|
-
console.log('Destination
|
|
83
|
+
console.log('Destination transaction:', result.destinationTx);
|
|
84
|
+
```
|
|
60
85
|
|
|
61
|
-
|
|
62
|
-
const feeEstimation = await sdk.estimateWithdrawalFee({
|
|
63
|
-
withdrawalParams: {
|
|
64
|
-
assetId: 'nep141:usdt.tether-token.near',
|
|
65
|
-
amount: 1000000n,
|
|
66
|
-
destinationAddress: '0x742d35Cc6634C0532925a3b8D84B2021F90a51A3',
|
|
67
|
-
feeInclusive: false
|
|
68
|
-
}
|
|
69
|
-
});
|
|
86
|
+
### Advanced Use Case: Custom Intents
|
|
70
87
|
|
|
71
|
-
|
|
72
|
-
withdrawalParams: {
|
|
73
|
-
assetId: 'nep141:usdt.tether-token.near',
|
|
74
|
-
amount: 1000000n,
|
|
75
|
-
destinationAddress: '0x742d35Cc6634C0532925a3b8D84B2021F90a51A3',
|
|
76
|
-
feeInclusive: false
|
|
77
|
-
},
|
|
78
|
-
feeEstimation
|
|
79
|
-
});
|
|
88
|
+
For advanced users who need custom intent logic beyond withdrawals, use the lower-level `signAndSendIntent` method:
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
```typescript
|
|
91
|
+
// Custom intent execution (advanced)
|
|
92
|
+
const result = await sdk.signAndSendIntent({
|
|
93
|
+
intents: [
|
|
94
|
+
{
|
|
95
|
+
intent: "transfer", // Custom intent type
|
|
96
|
+
receiver_id: "recipient.near",
|
|
97
|
+
tokens: {"usdt.tether-token.near": "1000000"}, // 1 USDT
|
|
98
|
+
},
|
|
99
|
+
],
|
|
90
100
|
});
|
|
101
|
+
|
|
102
|
+
console.log('Intent hash:', result.intentHash);
|
|
91
103
|
```
|
|
92
104
|
|
|
93
|
-
|
|
105
|
+
> **💡 Tip**: Use `processWithdrawal` for withdrawals and `signAndSendIntent` for custom intent logic. The withdrawal
|
|
106
|
+
> method handles fee estimation, validation, and completion tracking automatically.
|
|
94
107
|
|
|
95
|
-
|
|
108
|
+
## Core Functionalities
|
|
96
109
|
|
|
97
|
-
|
|
110
|
+
### Core Concepts
|
|
98
111
|
|
|
99
|
-
####
|
|
100
|
-
Routes define the **path** a withdrawal takes - the specific mechanism and destination for transferring assets. Each route represents a different withdrawal flow:
|
|
112
|
+
#### Intent
|
|
101
113
|
|
|
102
|
-
|
|
103
|
-
import { RouteEnum } from '@defuse-protocol/intents-sdk';
|
|
114
|
+
TBD
|
|
104
115
|
|
|
105
|
-
|
|
106
|
-
console.log(RouteEnum.PoaBridge); // "poa_bridge" - Cross-chain via PoA bridge
|
|
107
|
-
console.log(RouteEnum.NearWithdrawal); // "near_withdrawal" - Direct to NEAR blockchain
|
|
108
|
-
console.log(RouteEnum.VirtualChain); // "virtual_chain" - To Aurora Engine chains
|
|
109
|
-
console.log(RouteEnum.InternalTransfer); // "internal_transfer" - Between protocol users
|
|
110
|
-
```
|
|
116
|
+
#### Intent Signers
|
|
111
117
|
|
|
112
|
-
|
|
113
|
-
|
|
118
|
+
Intent signers are required to authenticate and sign both regular and withdrawal intents. The SDK supports
|
|
119
|
+
multiple signing methods:
|
|
114
120
|
|
|
115
|
-
|
|
116
|
-
|
|
121
|
+
| Singing Standard | Methods | Description |
|
|
122
|
+
|------------------|:------------------------------------------------------------------:|----------------------------------------------------------|
|
|
123
|
+
| nep413 | `createIntentSignerNEP413()`<br/>`createIntentSignerNearKeyPair()` | Almost all NEAR wallets support this standard |
|
|
124
|
+
| erc191 | `createIntentSignerViem()` | Only Viem library supported, Ethers.js signer is coming |
|
|
125
|
+
| raw_ed25519 | ❌ | Available on the protocol level, but not included to SDK |
|
|
126
|
+
| webauthn | ❌ | Available on the protocol level, but not included to SDK |
|
|
127
|
+
| ton_connect | ❌ | Available on the protocol level, but not included to SDK |
|
|
117
128
|
|
|
118
|
-
|
|
119
|
-
console.log(BridgeNameEnum.Poa); // "poa" - Proof-of-Authority bridge by Defuse Labs
|
|
120
|
-
console.log(BridgeNameEnum.None); // null - No external bridge (NEAR-native or internal)
|
|
121
|
-
```
|
|
129
|
+
You must set an intent signer before processing withdrawals:
|
|
122
130
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
131
|
+
```typescript
|
|
132
|
+
// Example: Set up a NEAR KeyPair signer
|
|
133
|
+
const signer = createIntentSignerNearKeyPair({
|
|
134
|
+
keypair: KeyPair.fromString('your-private-key'),
|
|
135
|
+
accountId: 'your-account.near'
|
|
136
|
+
});
|
|
137
|
+
sdk.setIntentSigner(signer);
|
|
138
|
+
```
|
|
126
139
|
|
|
127
|
-
|
|
140
|
+
See the [Intent Signers](#intent-signers-1) section below for detailed implementation examples.
|
|
128
141
|
|
|
129
|
-
|
|
142
|
+
#### Asset Identifiers
|
|
130
143
|
|
|
131
144
|
The SDK uses standardized asset identifiers in the format:
|
|
145
|
+
|
|
132
146
|
- `nep141:contract.near` - NEP-141 tokens
|
|
133
147
|
- `nep245:contract.near:tokenId` - NEP-245 multi-tokens
|
|
134
148
|
|
|
135
|
-
Asset Identifier uniquely determines the corresponding route and destination chain.
|
|
149
|
+
Asset Identifier uniquely determines the corresponding withdrawal route and destination chain.
|
|
136
150
|
|
|
137
151
|
Examples:
|
|
152
|
+
|
|
138
153
|
- `nep141:usdt.tether-token.near` - USDT on NEAR
|
|
139
154
|
- `nep141:wrap.near` - Wrapped NEAR (native NEAR)
|
|
140
155
|
- `nep245:v2_1.omni.hot.tg:137_qiStmoQJDQPTebaPjgx5VBxZv6L` - Polygon USDC through Hot
|
|
141
156
|
- `nep141:base-0x833589fcd6edb6e08f4c7c32d4f71b54bda02913.omft.near` - Base USDC through PoA
|
|
142
157
|
|
|
143
|
-
### Intent
|
|
158
|
+
### Intent Execution
|
|
144
159
|
|
|
145
|
-
|
|
160
|
+
The primary functionality of the SDK - execute custom intents on Near Intents:
|
|
146
161
|
|
|
147
|
-
- **
|
|
148
|
-
- **
|
|
149
|
-
- **
|
|
162
|
+
- **Sign Intents**: Create and sign intent payloads with various signer types
|
|
163
|
+
- **Submit Intents**: Publish intents to the Near Intents relayer network
|
|
164
|
+
- **Track Status**: Monitor intent settlement and execution status
|
|
165
|
+
- **Batch Intents**: Execute multiple intents in a single transaction
|
|
166
|
+
- **Custom Logic**: Support for any intent type supported by the protocol
|
|
150
167
|
|
|
151
|
-
|
|
168
|
+
```typescript
|
|
169
|
+
// Generic intent execution
|
|
170
|
+
const {intentHash} = await sdk.signAndSendIntent({
|
|
171
|
+
intents: [/* array of intent primitives */],
|
|
172
|
+
onBeforePublishIntent: async (data) => {
|
|
173
|
+
console.log('About to publish intent:', data.intentHash);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Monitor settlement
|
|
178
|
+
const intentTx = await sdk.waitForIntentSettlement({intentHash});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### Deposits
|
|
182
|
+
|
|
183
|
+
Deposit funds into Near Intents *(Coming Soon)*.
|
|
184
|
+
|
|
185
|
+
> **Note**: Deposit functionality is not yet implemented in this SDK. Currently, use bridge interfaces directly for
|
|
186
|
+
> deposit operations.
|
|
187
|
+
|
|
188
|
+
### Withdrawals
|
|
189
|
+
|
|
190
|
+
Complete withdrawal functionality from Near Intents to external chains:
|
|
191
|
+
|
|
192
|
+
- **Cross-Chain Transfers**: Withdraw to 20+ supported blockchains
|
|
193
|
+
- **Multi-Bridge Support**: Hot Bridge, PoA Bridge
|
|
194
|
+
- **Batch Processing**: Process multiple withdrawals at a time
|
|
195
|
+
- **Fee Management**: Automatic fee estimation with quote support
|
|
196
|
+
- **Validation**: Built-in validation for withdrawal constraints
|
|
197
|
+
- **Status Tracking**: End-to-end monitoring from intent to destination
|
|
152
198
|
|
|
153
199
|
```typescript
|
|
154
|
-
//
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
200
|
+
// Complete withdrawal process
|
|
201
|
+
const result = await sdk.processWithdrawal({
|
|
202
|
+
withdrawalParams: {
|
|
203
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
204
|
+
amount: 1000000n,
|
|
205
|
+
destinationAddress: '0x742d35Cc6634C0532925a3b8D84B2021F90a51A3',
|
|
206
|
+
feeInclusive: false
|
|
207
|
+
}
|
|
158
208
|
});
|
|
159
|
-
sdk.setIntentSigner(signer);
|
|
160
209
|
```
|
|
161
210
|
|
|
162
|
-
|
|
211
|
+
#### Routes and Bridges
|
|
212
|
+
|
|
213
|
+
The SDK uses two key concepts to organize withdrawal operations:
|
|
214
|
+
|
|
215
|
+
##### Routes
|
|
216
|
+
|
|
217
|
+
Routes define the **path** a withdrawal takes - the specific mechanism and destination for transferring assets. Each
|
|
218
|
+
route represents a different withdrawal flow:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
import {RouteEnum} from '@defuse-protocol/intents-sdk';
|
|
222
|
+
|
|
223
|
+
console.log(RouteEnum.HotBridge); // "hot_bridge" - Cross-chain via HOT protocol
|
|
224
|
+
console.log(RouteEnum.PoaBridge); // "poa_bridge" - Cross-chain via PoA bridge
|
|
225
|
+
console.log(RouteEnum.NearWithdrawal); // "near_withdrawal" - Direct to NEAR blockchain
|
|
226
|
+
console.log(RouteEnum.VirtualChain); // "virtual_chain" - To Aurora Engine chains
|
|
227
|
+
console.log(RouteEnum.InternalTransfer); // "internal_transfer" - Between protocol users
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
##### Bridge Names
|
|
231
|
+
|
|
232
|
+
Bridge names identify the **underlying bridge infrastructure** that handles the cross-chain transfer. This determines
|
|
233
|
+
which external protocol processes the withdrawal:
|
|
234
|
+
|
|
235
|
+
```typescript
|
|
236
|
+
import {BridgeNameEnum} from '@defuse-protocol/intents-sdk';
|
|
237
|
+
|
|
238
|
+
console.log(BridgeNameEnum.Hot); // "hot" - HOT Labs bridge infrastructure
|
|
239
|
+
console.log(BridgeNameEnum.Poa); // "poa" - Proof-of-Authority bridge by Defuse Labs
|
|
240
|
+
console.log(BridgeNameEnum.None); // null - No external bridge (NEAR-native or internal)
|
|
241
|
+
```
|
|
163
242
|
|
|
164
|
-
|
|
243
|
+
**Key Difference**:
|
|
244
|
+
|
|
245
|
+
- **Route** = "How and where" the withdrawal goes (the path)
|
|
246
|
+
- **Bridge Name** = "Who operates" the underlying infrastructure (the bridge provider)
|
|
247
|
+
|
|
248
|
+
For example, both `hot_bridge` and `poa_bridge` routes perform cross-chain transfers, but use different bridge
|
|
249
|
+
infrastructures (`hot` vs `poa`) with different fee structures and supported networks.
|
|
250
|
+
|
|
251
|
+
#### Route Types
|
|
165
252
|
|
|
166
253
|
The SDK automatically detects and supports multiple route types based on asset identifiers:
|
|
167
254
|
|
|
168
|
-
|
|
255
|
+
##### Hot Bridge Route
|
|
256
|
+
|
|
169
257
|
- **Purpose**: Cross-chain transfers via HOT Labs infrastructure
|
|
170
258
|
- **Supported Assets**: Multi-tokens (NEP-245) from Hot protocol (contract `v2_1.omni.hot.tg`)
|
|
171
259
|
- **Use Case**: Cross-chain transfers for assets bridged through Hot protocol
|
|
172
260
|
- **Route Type**: `hot_bridge`
|
|
173
261
|
|
|
174
|
-
|
|
262
|
+
##### PoA Bridge Route
|
|
263
|
+
|
|
175
264
|
- **Purpose**: Proof-of-Authority bridge transfers operated by Defuse Labs
|
|
176
265
|
- **Supported Assets**: Fungible tokens (NEP-141) ending with `.omft.near`
|
|
177
266
|
- **Use Case**: Cross-chain transfers for assets bridged through PoA protocol
|
|
178
267
|
- **Route Type**: `poa_bridge`
|
|
179
268
|
|
|
180
|
-
|
|
269
|
+
##### Internal Transfer Route
|
|
270
|
+
|
|
181
271
|
- **Purpose**: Transfer between Near Intents users within the protocol
|
|
182
272
|
- **Supported Assets**: All NEP-141 and NEP-245 tokens
|
|
183
273
|
- **Use Case**: User A having funds in the protocol wants to transfer to User B
|
|
184
274
|
- **Route Type**: `internal_transfer`
|
|
185
275
|
|
|
186
|
-
|
|
276
|
+
##### Near Withdrawal Route
|
|
277
|
+
|
|
187
278
|
- **Purpose**: Transfers within the NEAR blockchain
|
|
188
279
|
- **Supported Assets**: NEP-141 tokens on NEAR, including native NEAR (wrap.near)
|
|
189
280
|
- **Use Case**: Same-chain transfers on NEAR
|
|
190
281
|
- **Route Type**: `near_withdrawal`
|
|
191
282
|
|
|
192
|
-
|
|
283
|
+
##### Virtual Chain Route
|
|
284
|
+
|
|
193
285
|
- **Purpose**: Transfers to Aurora Engine-powered chains (aka Virtual chains)
|
|
194
286
|
- **Supported Assets**: NEP-141 tokens with Aurora Engine integration
|
|
195
287
|
- **Use Case**: Near Intents to Aurora ecosystem transfers
|
|
196
288
|
- **Route Type**: `virtual_chain`
|
|
197
289
|
- **Note**: Requires explicit `routeConfig` with `auroraEngineContractId`
|
|
198
290
|
|
|
199
|
-
|
|
291
|
+
#### Fee Estimation
|
|
200
292
|
|
|
201
293
|
The SDK now supports both single and batch fee estimation:
|
|
202
294
|
|
|
203
295
|
```typescript
|
|
204
296
|
// Single withdrawal fee estimation
|
|
205
297
|
const feeEstimation = await sdk.estimateWithdrawalFee({
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
298
|
+
withdrawalParams: {
|
|
299
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
300
|
+
amount: 1000000n,
|
|
301
|
+
destinationAddress: '0x742d35Cc6634C0532925a3b8D84B2021F90a51A3',
|
|
302
|
+
feeInclusive: false
|
|
303
|
+
}
|
|
212
304
|
});
|
|
213
305
|
|
|
214
306
|
console.log('Fee amount:', feeEstimation.amount);
|
|
@@ -216,61 +308,83 @@ console.log('Quote info:', feeEstimation.quote); // null if fee paid with withdr
|
|
|
216
308
|
|
|
217
309
|
// Batch fee estimation
|
|
218
310
|
const batchFees = await sdk.estimateWithdrawalFee({
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
311
|
+
withdrawalParams: [
|
|
312
|
+
{
|
|
313
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
314
|
+
amount: 1000000n,
|
|
315
|
+
destinationAddress: '0x742d35Cc...',
|
|
316
|
+
feeInclusive: false
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
assetId: 'nep245:v2_1.omni.hot.tg:137_qiStmoQJDQPTebaPjgx5VBxZv6L',
|
|
320
|
+
amount: 500000n,
|
|
321
|
+
destinationAddress: '0x742d35Cc...',
|
|
322
|
+
feeInclusive: false
|
|
323
|
+
}
|
|
324
|
+
]
|
|
233
325
|
});
|
|
234
326
|
|
|
235
327
|
console.log('Batch fees:', batchFees); // Array of FeeEstimation objects
|
|
236
328
|
```
|
|
237
329
|
|
|
238
|
-
|
|
330
|
+
## Advanced Usage
|
|
331
|
+
|
|
332
|
+
### Custom RPC URLs
|
|
333
|
+
|
|
334
|
+
Set NEAR and EVM chains RPC URLs in the constructor:
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
import {Chains} from '@defuse-protocol/intents-sdk'
|
|
338
|
+
|
|
339
|
+
const sdk = new IntentsSDK({
|
|
340
|
+
...,
|
|
341
|
+
rpc: {
|
|
342
|
+
[Chains.Near]: ['https://rpc.mainnet.near.org'],
|
|
343
|
+
[Chains.Polygon]: ['https://polygon-rpc.com'],
|
|
344
|
+
[Chains.BNB]: ['https://bsc-dataseed.binance.org'],
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Other Intent Signers
|
|
239
350
|
|
|
240
351
|
The SDK supports multiple intent signing methods using factory functions:
|
|
241
352
|
|
|
242
353
|
#### NEAR KeyPair Signer
|
|
354
|
+
|
|
243
355
|
```typescript
|
|
244
|
-
import {
|
|
245
|
-
import {
|
|
356
|
+
import {createIntentSignerNearKeyPair, IntentsSDK} from '@defuse-protocol/intents-sdk';
|
|
357
|
+
import {KeyPair} from 'near-api-js';
|
|
246
358
|
|
|
247
359
|
const keyPair = KeyPair.fromString('your-private-key');
|
|
248
360
|
const signer = createIntentSignerNearKeyPair({
|
|
249
|
-
|
|
250
|
-
|
|
361
|
+
keypair: keyPair,
|
|
362
|
+
accountId: 'your-account.near'
|
|
251
363
|
});
|
|
252
364
|
```
|
|
253
365
|
|
|
254
366
|
#### NEP-413 Signer
|
|
367
|
+
|
|
255
368
|
```typescript
|
|
256
|
-
import {
|
|
369
|
+
import {createIntentSignerNEP413} from '@defuse-protocol/intents-sdk';
|
|
257
370
|
|
|
258
371
|
const signer = createIntentSignerNEP413({
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
372
|
+
signMessage: async (nep413Payload, nep413Hash) => {
|
|
373
|
+
// Implement your custom signing logic here
|
|
374
|
+
return {
|
|
375
|
+
publicKey: 'ed25519:YourPublicKey',
|
|
376
|
+
signature: 'base64-encoded-signature'
|
|
377
|
+
};
|
|
378
|
+
},
|
|
379
|
+
accountId: 'your-account.near'
|
|
267
380
|
});
|
|
268
381
|
```
|
|
269
382
|
|
|
270
383
|
#### EVM/Viem Signer
|
|
384
|
+
|
|
271
385
|
```typescript
|
|
272
|
-
import {
|
|
273
|
-
import {
|
|
386
|
+
import {createIntentSignerViem} from '@defuse-protocol/intents-sdk';
|
|
387
|
+
import {privateKeyToAccount} from 'viem/accounts';
|
|
274
388
|
|
|
275
389
|
const account = privateKeyToAccount('0x...');
|
|
276
390
|
const signer = createIntentSignerViem(account);
|
|
@@ -279,79 +393,63 @@ const signer = createIntentSignerViem(account);
|
|
|
279
393
|
sdk.setIntentSigner(signer);
|
|
280
394
|
```
|
|
281
395
|
|
|
282
|
-
## Advanced Usage
|
|
283
|
-
|
|
284
|
-
### Custom RPC URLs
|
|
285
|
-
|
|
286
|
-
Set NEAR and EVM chains RPC URLs in the constructor:
|
|
287
|
-
|
|
288
|
-
```typescript
|
|
289
|
-
import { Chains } from '@defuse-protocol/intents-sdk'
|
|
290
|
-
|
|
291
|
-
const sdk = new IntentsSDK({
|
|
292
|
-
...,
|
|
293
|
-
rpc: {
|
|
294
|
-
[Chains.Near]: ['https://rpc.mainnet.near.org'],
|
|
295
|
-
[Chains.Polygon]: ['https://polygon-rpc.com'],
|
|
296
|
-
[Chains.BNB]: ['https://bsc-dataseed.binance.org'],
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
```
|
|
300
|
-
|
|
301
396
|
### Intent Publishing Hooks
|
|
302
397
|
|
|
303
|
-
Use the `onBeforePublishIntent` hook to intercept and process intent data before it's published to the relayer. This is
|
|
398
|
+
Use the `onBeforePublishIntent` hook to intercept and process intent data before it's published to the relayer. This is
|
|
399
|
+
useful for persistence, logging, analytics, or custom processing:
|
|
304
400
|
|
|
305
401
|
```typescript
|
|
306
|
-
import {
|
|
402
|
+
import {type OnBeforePublishIntentHook} from '@defuse-protocol/intents-sdk';
|
|
307
403
|
|
|
308
404
|
// Define your hook function
|
|
309
405
|
const onBeforePublishIntent: OnBeforePublishIntentHook = async (intentData) => {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
406
|
+
// Save to database for tracking
|
|
407
|
+
await saveIntentToDatabase({
|
|
408
|
+
hash: intentData.intentHash,
|
|
409
|
+
payload: intentData.intentPayload,
|
|
410
|
+
timestamp: new Date(),
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
// Send analytics
|
|
414
|
+
analytics.track('intent_about_to_publish', {
|
|
415
|
+
intentHash: intentData.intentHash,
|
|
416
|
+
intentType: intentData.intentPayload.intents[0]?.intent,
|
|
417
|
+
});
|
|
322
418
|
};
|
|
323
419
|
|
|
324
420
|
// Use the hook with the functional API
|
|
325
421
|
const result = await sdk.processWithdrawal({
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
422
|
+
withdrawalParams: { /* ... */},
|
|
423
|
+
intent: {
|
|
424
|
+
onBeforePublishIntent, // Add the hook here
|
|
425
|
+
}
|
|
330
426
|
});
|
|
331
427
|
|
|
332
428
|
// Or with granular control
|
|
333
|
-
const {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
429
|
+
const {intentHash} = await sdk.signAndSendWithdrawalIntent({
|
|
430
|
+
withdrawalParams: { /* ... */},
|
|
431
|
+
feeEstimation: fee,
|
|
432
|
+
intent: {
|
|
433
|
+
onBeforePublishIntent, // Add the hook here
|
|
434
|
+
}
|
|
339
435
|
});
|
|
340
436
|
|
|
341
437
|
// Or with generic intent publishing
|
|
342
|
-
const {
|
|
343
|
-
|
|
344
|
-
|
|
438
|
+
const {intentHash} = await sdk.signAndSendIntent({
|
|
439
|
+
intents: [/* ... */],
|
|
440
|
+
onBeforePublishIntent, // Add the hook here
|
|
345
441
|
});
|
|
346
442
|
```
|
|
347
443
|
|
|
348
444
|
**Hook Parameters:**
|
|
445
|
+
|
|
349
446
|
- `intentHash` - The computed hash of the intent payload
|
|
350
447
|
- `intentPayload` - The unsigned intent payload
|
|
351
448
|
- `multiPayload` - The signed multi-payload containing signature and metadata
|
|
352
449
|
- `relayParams` - Additional parameters passed to the relayer (quote hashes)
|
|
353
450
|
|
|
354
451
|
**Important Notes:**
|
|
452
|
+
|
|
355
453
|
- The hook is called synchronously before publishing the intent
|
|
356
454
|
- If the hook throws an error, the withdrawal will fail
|
|
357
455
|
- The hook can be async and return a Promise
|
|
@@ -362,24 +460,24 @@ Process multiple withdrawals in a single intent:
|
|
|
362
460
|
|
|
363
461
|
```typescript
|
|
364
462
|
const withdrawalParams = [
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
463
|
+
{
|
|
464
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
465
|
+
amount: 1000000n,
|
|
466
|
+
destinationAddress: '0x742d35Cc...',
|
|
467
|
+
feeInclusive: false
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
assetId: 'nep245:v2_1.omni.hot.tg:137_qiStmoQJDQPTebaPjgx5VBxZv6L',
|
|
471
|
+
amount: 100000n,
|
|
472
|
+
destinationAddress: '0x742d35Cc...',
|
|
473
|
+
feeInclusive: false
|
|
474
|
+
}
|
|
377
475
|
]
|
|
378
476
|
|
|
379
477
|
// Method 1: Complete end-to-end batch processing
|
|
380
478
|
const batchResult = await sdk.processWithdrawal({
|
|
381
|
-
|
|
382
|
-
|
|
479
|
+
withdrawalParams,
|
|
480
|
+
// feeEstimation is optional - will be estimated automatically if not provided
|
|
383
481
|
});
|
|
384
482
|
|
|
385
483
|
console.log('Batch intent hash:', batchResult.intentHash);
|
|
@@ -387,19 +485,19 @@ console.log('Destination transactions:', batchResult.destinationTx); // Array of
|
|
|
387
485
|
|
|
388
486
|
// Method 2: Step-by-step batch processing for granular control
|
|
389
487
|
const feeEstimation = await sdk.estimateWithdrawalFee({
|
|
390
|
-
|
|
488
|
+
withdrawalParams
|
|
391
489
|
});
|
|
392
490
|
|
|
393
|
-
const {
|
|
394
|
-
|
|
395
|
-
|
|
491
|
+
const {intentHash} = await sdk.signAndSendWithdrawalIntent({
|
|
492
|
+
withdrawalParams,
|
|
493
|
+
feeEstimation
|
|
396
494
|
});
|
|
397
495
|
|
|
398
|
-
const intentTx = await sdk.waitForIntentSettlement({
|
|
496
|
+
const intentTx = await sdk.waitForIntentSettlement({intentHash});
|
|
399
497
|
|
|
400
498
|
const destinationTxs = await sdk.waitForWithdrawalCompletion({
|
|
401
|
-
|
|
402
|
-
|
|
499
|
+
withdrawalParams,
|
|
500
|
+
intentTx
|
|
403
501
|
});
|
|
404
502
|
|
|
405
503
|
console.log('All destination transactions:', destinationTxs);
|
|
@@ -411,60 +509,62 @@ The SDK provides direct access to intent operations for advanced use cases:
|
|
|
411
509
|
|
|
412
510
|
```typescript
|
|
413
511
|
// Generic intent signing and publishing
|
|
414
|
-
const {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
512
|
+
const {intentHash} = await sdk.signAndSendIntent({
|
|
513
|
+
intents: [/* array of intent primitives */],
|
|
514
|
+
signer: customIntentSigner, // optional - uses SDK default if not provided
|
|
515
|
+
onBeforePublishIntent: async (data) => {
|
|
516
|
+
// Custom logic before publishing
|
|
517
|
+
console.log('About to publish intent:', data.intentHash);
|
|
518
|
+
}
|
|
421
519
|
});
|
|
422
520
|
|
|
423
521
|
// Wait for intent settlement
|
|
424
|
-
const intentTx = await sdk.waitForIntentSettlement({
|
|
425
|
-
|
|
522
|
+
const intentTx = await sdk.waitForIntentSettlement({
|
|
523
|
+
intentHash
|
|
426
524
|
});
|
|
427
525
|
|
|
428
526
|
// or manual status check
|
|
429
527
|
|
|
430
528
|
// Check intent status at any time
|
|
431
|
-
const status = await sdk.getIntentStatus({
|
|
432
|
-
|
|
529
|
+
const status = await sdk.getIntentStatus({
|
|
530
|
+
intentHash: intentHash
|
|
433
531
|
});
|
|
434
532
|
|
|
435
533
|
console.log('Intent status:', status.status); // "PENDING" | "TX_BROADCASTED" | "SETTLED" | "NOT_FOUND_OR_NOT_VALID"
|
|
436
534
|
|
|
437
535
|
if (status.status === 'SETTLED') {
|
|
438
|
-
|
|
536
|
+
console.log('Settlement transaction:', status.txHash);
|
|
439
537
|
}
|
|
440
538
|
```
|
|
441
539
|
|
|
442
540
|
**Intent Status Values:**
|
|
541
|
+
|
|
443
542
|
- `PENDING` - Intent published but not yet processed
|
|
444
543
|
- `TX_BROADCASTED` - Intent being processed, transaction broadcasted
|
|
445
544
|
- `SETTLED` - Intent successfully completed
|
|
446
545
|
- `NOT_FOUND_OR_NOT_VALID` - Intent not found or invalid, it isn't executed onchain
|
|
447
546
|
|
|
448
|
-
###
|
|
547
|
+
### Configure Withdrawal Routes
|
|
449
548
|
|
|
450
|
-
**Recommended**: Use factory functions to create route configurations. The SDK provides factory functions for type-safe
|
|
549
|
+
**Recommended**: Use factory functions to create route configurations. The SDK provides factory functions for type-safe
|
|
550
|
+
and convenient route configuration creation:
|
|
451
551
|
|
|
452
552
|
```typescript
|
|
453
|
-
import {
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
553
|
+
import {
|
|
554
|
+
createVirtualChainRoute,
|
|
555
|
+
createNearWithdrawalRoute,
|
|
556
|
+
createInternalTransferRoute
|
|
457
557
|
} from '@defuse-protocol/intents-sdk';
|
|
458
558
|
|
|
459
559
|
// Create virtual chain route configuration (recommended)
|
|
460
560
|
const virtualChainRoute = createVirtualChainRoute(
|
|
461
|
-
|
|
462
|
-
|
|
561
|
+
'0x4e45415f.c.aurora', // Aurora Engine contract ID
|
|
562
|
+
null // Proxy token contract ID (optional)
|
|
463
563
|
);
|
|
464
564
|
|
|
465
565
|
// Create near withdrawal route with custom message
|
|
466
566
|
const nearWithdrawalRoute = createNearWithdrawalRoute(
|
|
467
|
-
|
|
567
|
+
'Custom withdrawal message' // Optional message
|
|
468
568
|
);
|
|
469
569
|
|
|
470
570
|
// Create internal transfer route
|
|
@@ -472,13 +572,13 @@ const internalTransferRoute = createInternalTransferRoute();
|
|
|
472
572
|
|
|
473
573
|
// Use the factory-created route configuration in withdrawal
|
|
474
574
|
const result = await sdk.processWithdrawal({
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
575
|
+
withdrawalParams: {
|
|
576
|
+
assetId: 'nep141:a35923162c49cf95e6bf26623385eb431ad920d3.factory.bridge.near',
|
|
577
|
+
amount: BigInt('1000000'),
|
|
578
|
+
destinationAddress: '0x742d35Cc6634C0532925a3b8D84B2021F90a51A3',
|
|
579
|
+
feeInclusive: false,
|
|
580
|
+
routeConfig: virtualChainRoute // Recommended: Use factory function
|
|
581
|
+
}
|
|
482
582
|
});
|
|
483
583
|
```
|
|
484
584
|
|
|
@@ -488,13 +588,13 @@ Get detailed information about supported assets:
|
|
|
488
588
|
|
|
489
589
|
```typescript
|
|
490
590
|
try {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
591
|
+
const assetInfo = sdk.parseAssetId('nep141:usdt.tether-token.near');
|
|
592
|
+
console.log('Bridge name:', assetInfo.bridgeName);
|
|
593
|
+
console.log('Blockchain:', assetInfo.blockchain);
|
|
594
|
+
console.log('Contract ID:', assetInfo.contractId);
|
|
595
|
+
console.log('Standard:', assetInfo.standard);
|
|
496
596
|
} catch (error) {
|
|
497
|
-
|
|
597
|
+
console.log('Asset not supported');
|
|
498
598
|
}
|
|
499
599
|
```
|
|
500
600
|
|
|
@@ -505,12 +605,12 @@ Monitor withdrawal completion:
|
|
|
505
605
|
```typescript
|
|
506
606
|
// Method 1: Using the orchestrated approach (automatic monitoring)
|
|
507
607
|
const result = await sdk.processWithdrawal({
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
608
|
+
withdrawalParams: {
|
|
609
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
610
|
+
amount: 1000000n,
|
|
611
|
+
destinationAddress: '0x742d35Cc...',
|
|
612
|
+
feeInclusive: false
|
|
613
|
+
}
|
|
514
614
|
});
|
|
515
615
|
|
|
516
616
|
console.log('Intent settled:', result.intentTx.hash);
|
|
@@ -518,162 +618,169 @@ console.log('Withdrawal completed:', result.destinationTx);
|
|
|
518
618
|
|
|
519
619
|
// Method 2: Step-by-step monitoring for granular control
|
|
520
620
|
const feeEstimation = await sdk.estimateWithdrawalFee({
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
621
|
+
withdrawalParams: {
|
|
622
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
623
|
+
amount: 1000000n,
|
|
624
|
+
destinationAddress: '0x742d35Cc...',
|
|
625
|
+
feeInclusive: false
|
|
626
|
+
}
|
|
527
627
|
});
|
|
528
628
|
|
|
529
|
-
const {
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
629
|
+
const {intentHash} = await sdk.signAndSendWithdrawalIntent({
|
|
630
|
+
withdrawalParams: {
|
|
631
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
632
|
+
amount: 1000000n,
|
|
633
|
+
destinationAddress: '0x742d35Cc...',
|
|
634
|
+
feeInclusive: false
|
|
635
|
+
},
|
|
636
|
+
feeEstimation
|
|
537
637
|
});
|
|
538
638
|
|
|
539
639
|
// Monitor intent settlement
|
|
540
|
-
const intentTx = await sdk.waitForIntentSettlement({
|
|
640
|
+
const intentTx = await sdk.waitForIntentSettlement({intentHash});
|
|
541
641
|
console.log('Intent settled:', intentTx.hash);
|
|
542
642
|
|
|
543
643
|
// Wait for withdrawal completion on destination chain
|
|
544
644
|
const completionResult = await sdk.waitForWithdrawalCompletion({
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
645
|
+
withdrawalParams: {
|
|
646
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
647
|
+
amount: 1000000n,
|
|
648
|
+
destinationAddress: '0x742d35Cc...',
|
|
649
|
+
feeInclusive: false
|
|
650
|
+
},
|
|
651
|
+
intentTx
|
|
552
652
|
});
|
|
553
653
|
|
|
554
654
|
if ('hash' in completionResult) {
|
|
555
|
-
|
|
655
|
+
console.log('Withdrawal completed with hash:', completionResult.hash);
|
|
556
656
|
} else {
|
|
557
|
-
|
|
657
|
+
console.log('Withdrawal completion not trackable for this bridge');
|
|
558
658
|
}
|
|
559
659
|
```
|
|
560
660
|
|
|
561
661
|
### Error Handling
|
|
562
662
|
|
|
563
663
|
```typescript
|
|
564
|
-
import {
|
|
664
|
+
import {FeeExceedsAmountError, MinWithdrawalAmountError} from '@defuse-protocol/intents-sdk';
|
|
565
665
|
|
|
566
666
|
try {
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
667
|
+
const result = await sdk.processWithdrawal({
|
|
668
|
+
withdrawalParams: {
|
|
669
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
670
|
+
amount: BigInt('100'), // Very small amount
|
|
671
|
+
destinationAddress: '0x742d35Cc...',
|
|
672
|
+
feeInclusive: true // Fee must be less than amount
|
|
673
|
+
}
|
|
674
|
+
});
|
|
575
675
|
} catch (error) {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
676
|
+
if (error instanceof FeeExceedsAmountError) {
|
|
677
|
+
console.log('Fee exceeds withdrawal amount');
|
|
678
|
+
console.log('Required fee:', error.feeEstimation.amount);
|
|
679
|
+
console.log('Withdrawal amount:', error.amount);
|
|
680
|
+
} else if (error instanceof MinWithdrawalAmountError) {
|
|
681
|
+
console.log('Amount below minimum withdrawal limit');
|
|
682
|
+
console.log('Minimum required:', error.minAmount);
|
|
683
|
+
console.log('Requested amount:', error.requestedAmount);
|
|
684
|
+
console.log('Asset:', error.assetId);
|
|
685
|
+
}
|
|
586
686
|
}
|
|
587
687
|
|
|
588
688
|
// Error handling with granular control
|
|
589
689
|
try {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
690
|
+
const feeEstimation = await sdk.estimateWithdrawalFee({
|
|
691
|
+
withdrawalParams: {
|
|
692
|
+
assetId: 'nep141:usdt.tether-token.near',
|
|
693
|
+
amount: 100n,
|
|
694
|
+
destinationAddress: '0x742d35Cc...',
|
|
695
|
+
feeInclusive: true
|
|
696
|
+
}
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
// Continue with other operations...
|
|
600
700
|
} catch (error) {
|
|
601
|
-
|
|
602
|
-
|
|
701
|
+
// Handle specific errors at each step
|
|
702
|
+
console.error('Fee estimation failed:', error);
|
|
603
703
|
}
|
|
604
704
|
```
|
|
605
705
|
|
|
606
706
|
#### PoA Bridge Minimum Withdrawal Amount Validation
|
|
607
707
|
|
|
608
|
-
PoA bridge has minimum withdrawal amount requirements that vary per token and blockchain. The SDK automatically
|
|
708
|
+
PoA bridge has minimum withdrawal amount requirements that vary per token and blockchain. The SDK automatically
|
|
709
|
+
validates this for all withdrawals.
|
|
609
710
|
|
|
610
711
|
```typescript
|
|
611
712
|
// Validation happens automatically during withdrawal processing:
|
|
612
713
|
try {
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
714
|
+
const result = await sdk.processWithdrawal({
|
|
715
|
+
withdrawalParams: {
|
|
716
|
+
assetId: 'nep141:zec.omft.near', // Zcash token
|
|
717
|
+
amount: BigInt('50000000'), // 0.5 ZEC (in smallest units)
|
|
718
|
+
destinationAddress: 'your-zcash-address',
|
|
719
|
+
feeInclusive: false
|
|
720
|
+
}
|
|
721
|
+
});
|
|
621
722
|
} catch (error) {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
723
|
+
if (error instanceof MinWithdrawalAmountError) {
|
|
724
|
+
console.log(`Minimum withdrawal for ${error.assetId}: ${error.minAmount}`);
|
|
725
|
+
console.log(`Requested amount: ${error.requestedAmount}`);
|
|
726
|
+
// For Zcash: minimum is typically 1.0 ZEC (100000000 in smallest units)
|
|
727
|
+
// Plus 0.2 ZEC fee, so user needs at least 1.2 ZEC to withdraw 1.0 ZEC
|
|
728
|
+
}
|
|
628
729
|
}
|
|
629
730
|
```
|
|
630
731
|
|
|
631
|
-
Note: Other routes (Near Withdrawal, Virtual Chain, Internal Transfer) don't have minimum withdrawal restrictions, so
|
|
732
|
+
Note: Other routes (Near Withdrawal, Virtual Chain, Internal Transfer) don't have minimum withdrawal restrictions, so
|
|
733
|
+
validation passes through for those routes.
|
|
632
734
|
|
|
633
735
|
#### Hot Bridge Stellar Trustline Validation
|
|
634
736
|
|
|
635
|
-
Hot Bridge validates that destination addresses have the required trustlines when withdrawing to Stellar blockchain.
|
|
737
|
+
Hot Bridge validates that destination addresses have the required trustlines when withdrawing to Stellar blockchain.
|
|
738
|
+
This prevents failed transactions due to missing trustlines.
|
|
636
739
|
|
|
637
740
|
```typescript
|
|
638
|
-
import {
|
|
741
|
+
import {TrustlineNotFoundError} from '@defuse-protocol/intents-sdk';
|
|
639
742
|
|
|
640
743
|
// Validation happens automatically during withdrawal processing:
|
|
641
744
|
try {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
745
|
+
const result = await sdk.processWithdrawal({
|
|
746
|
+
withdrawalParams: {
|
|
747
|
+
assetId: 'nep245:v2_1.omni.hot.tg:stellar_1_USD_GBDMM6LG7YX7YGF6JFAEWX3KFUSBXGAEPZ2IHDLWH:1100', // Stellar USD token
|
|
748
|
+
amount: BigInt('1000000'), // 1 USD (in smallest units)
|
|
749
|
+
destinationAddress: 'GCKFBEIYTKP6RYVDYGMVVMJ6J6XKCRZL74JPWTFGD2NQNMPBQC2LGTVZ', // Stellar address
|
|
750
|
+
feeInclusive: false
|
|
751
|
+
}
|
|
752
|
+
});
|
|
650
753
|
} catch (error) {
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
754
|
+
if (error instanceof TrustlineNotFoundError) {
|
|
755
|
+
console.log(`Trustline not found for token: ${error.assetId}`);
|
|
756
|
+
console.log(`Destination address: ${error.destinationAddress}`);
|
|
757
|
+
console.log('The destination address must have a trustline for this token before withdrawal');
|
|
758
|
+
// User needs to create a trustline for the token on Stellar before withdrawing
|
|
759
|
+
}
|
|
657
760
|
}
|
|
658
761
|
```
|
|
659
762
|
|
|
660
763
|
**What is a trustline?**
|
|
661
|
-
On Stellar, accounts must explicitly create "trustlines" to hold non-native assets. Before receiving any token (except
|
|
764
|
+
On Stellar, accounts must explicitly create "trustlines" to hold non-native assets. Before receiving any token (except
|
|
765
|
+
XLM), the destination address must:
|
|
766
|
+
|
|
662
767
|
1. Create a trustline for that specific token
|
|
663
768
|
2. Have sufficient XLM balance to maintain the trustline
|
|
664
769
|
|
|
665
770
|
**Why this validation matters:**
|
|
771
|
+
|
|
666
772
|
- Prevents failed withdrawals due to missing trustlines
|
|
667
773
|
- Saves gas fees and reduces user frustration
|
|
668
774
|
- Provides clear error messages for troubleshooting
|
|
669
775
|
|
|
670
|
-
Note: This validation only applies to Stellar destinations via Hot Bridge. Other blockchains and routes don't require
|
|
671
|
-
|
|
672
|
-
TBD
|
|
776
|
+
Note: This validation only applies to Stellar destinations via Hot Bridge. Other blockchains and routes don't require
|
|
777
|
+
trustline validation.
|
|
673
778
|
|
|
674
779
|
## Supported Networks
|
|
675
780
|
|
|
676
|
-
For a list of supported chains, see
|
|
781
|
+
For a list of supported chains, see
|
|
782
|
+
the [Chain Support page](https://docs.near-intents.org/near-intents/chain-address-support) in the Near Intents
|
|
783
|
+
documentation.
|
|
677
784
|
|
|
678
785
|
## Development
|
|
679
786
|
|