@fystack/sdk 0.1.10 → 0.1.11
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/api.sh +42 -0
- package/dist/index.cjs +93 -5
- package/dist/index.d.cts +338 -247
- package/dist/index.d.mts +338 -247
- package/dist/index.esm.d.ts +338 -247
- package/dist/index.esm.js +93 -6
- package/dist/index.mjs +93 -6
- package/dist/types/index.d.ts +338 -247
- package/package.json +1 -1
- package/readme.md +203 -158
- package/src/api.ts +32 -1
- package/src/config.ts +8 -3
- package/src/enum.ts +14 -0
- package/src/sdk.ts +57 -6
- package/src/types.ts +56 -0
- package/test.js +0 -76
package/readme.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Fystack Platform SDK
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A TypeScript SDK for Fystack's wallet and payment services, providing seamless integration with EVM, Solana, and Tron blockchains.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,199 +8,244 @@ A Typescript SDK for Fystack's wallet and payment services, providing seamless i
|
|
|
8
8
|
npm install @fystack/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
### Wallet Management
|
|
14
|
-
|
|
15
|
-
Create and manage blockchain wallets with minimal code.
|
|
11
|
+
## Quick Start
|
|
16
12
|
|
|
17
13
|
```typescript
|
|
18
|
-
import { FystackSDK } from '@fystack/sdk'
|
|
19
|
-
import { Environment, WalletType } from '@fystack/sdk'
|
|
14
|
+
import { FystackSDK, Environment } from '@fystack/sdk'
|
|
20
15
|
|
|
21
|
-
//
|
|
16
|
+
// Find your workspace ID at https://app.fystack.io -> Developers -> API Key
|
|
22
17
|
const sdk = new FystackSDK({
|
|
23
18
|
credentials: {
|
|
24
19
|
apiKey: 'YOUR_API_KEY',
|
|
25
20
|
apiSecret: 'YOUR_API_SECRET'
|
|
26
21
|
},
|
|
22
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
27
23
|
environment: Environment.Production,
|
|
28
|
-
|
|
24
|
+
debug: true // Enable debug logging
|
|
29
25
|
})
|
|
26
|
+
```
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
28
|
+
## Create Wallet
|
|
29
|
+
|
|
30
|
+
Fystack supports two wallet types:
|
|
31
|
+
|
|
32
|
+
- **Hyper** — Instantly created wallet. No async provisioning needed.
|
|
33
|
+
- **MPC** — Multi-Party Computation wallet with distributed key management. Creation is async and requires polling for status.
|
|
34
|
+
|
|
35
|
+
### Hyper Wallet
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { WalletType, WalletPurpose } from '@fystack/sdk'
|
|
39
|
+
|
|
40
|
+
const wallet = await sdk.createWallet({
|
|
41
|
+
name: 'Treasury Wallet',
|
|
42
|
+
walletType: WalletType.Hyper,
|
|
43
|
+
walletPurpose: WalletPurpose.General
|
|
40
44
|
})
|
|
41
45
|
|
|
42
|
-
console.log('Wallet ID:',
|
|
43
|
-
|
|
46
|
+
console.log('Wallet ID:', wallet.wallet_id)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### MPC Wallet
|
|
50
|
+
|
|
51
|
+
MPC wallets are provisioned asynchronously. By default, `createWallet` waits for provisioning to complete before returning:
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
const wallet = await sdk.createWallet({
|
|
55
|
+
name: 'MPC Wallet',
|
|
56
|
+
walletType: WalletType.MPC,
|
|
57
|
+
walletPurpose: WalletPurpose.General
|
|
58
|
+
})
|
|
44
59
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
console.log('WalletID:', statusResponse.wallet_id)
|
|
60
|
+
console.log('Wallet ID:', wallet.wallet_id)
|
|
61
|
+
console.log('Status:', wallet.status) // 'success' or 'error'
|
|
48
62
|
```
|
|
49
63
|
|
|
50
|
-
|
|
64
|
+
To return immediately and poll status manually:
|
|
51
65
|
|
|
52
66
|
```typescript
|
|
53
|
-
|
|
54
|
-
|
|
67
|
+
const wallet = await sdk.createWallet(
|
|
68
|
+
{ name: 'MPC Wallet', walletType: WalletType.MPC },
|
|
69
|
+
false // don't wait for completion
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
// Poll status every 2 seconds until provisioned
|
|
73
|
+
const interval = setInterval(async () => {
|
|
74
|
+
const status = await sdk.getWalletCreationStatus(wallet.wallet_id)
|
|
75
|
+
console.log('Status:', status.status)
|
|
76
|
+
|
|
77
|
+
if (status.status === 'success' || status.status === 'error') {
|
|
78
|
+
clearInterval(interval)
|
|
79
|
+
}
|
|
80
|
+
}, 2000)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Get Deposit Address
|
|
84
|
+
|
|
85
|
+
Retrieve deposit addresses for a specific wallet and address type.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { AddressType } from '@fystack/sdk'
|
|
89
|
+
|
|
90
|
+
// Get EVM deposit address
|
|
91
|
+
const evm = await sdk.getDepositAddress(wallet.wallet_id, AddressType.Evm)
|
|
92
|
+
console.log('EVM Address:', evm.address)
|
|
93
|
+
|
|
94
|
+
// Get Solana deposit address
|
|
95
|
+
const sol = await sdk.getDepositAddress(wallet.wallet_id, AddressType.Solana)
|
|
96
|
+
console.log('Solana Address:', sol.address)
|
|
97
|
+
|
|
98
|
+
// Get Tron deposit address
|
|
99
|
+
const tron = await sdk.getDepositAddress(wallet.wallet_id, AddressType.Tron)
|
|
100
|
+
console.log('Tron Address:', tron.address)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Create Withdrawal
|
|
104
|
+
|
|
105
|
+
Request a withdrawal from a wallet to an external address.
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
const withdrawal = await sdk.requestWithdrawal('WALLET_ID', {
|
|
109
|
+
assetId: 'ASSET_UUID',
|
|
110
|
+
amount: '10.5',
|
|
111
|
+
recipientAddress: '0xRecipientAddress',
|
|
112
|
+
notes: 'Monthly payout'
|
|
113
|
+
})
|
|
55
114
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
{
|
|
60
|
-
apiKey: 'YOUR_API_KEY',
|
|
61
|
-
apiSecret: 'YOUR_API_SECRET'
|
|
62
|
-
},
|
|
63
|
-
Environment.Production
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
// Get signer's address
|
|
67
|
-
const fromAddress = await signer.getAddress()
|
|
68
|
-
const fromPubkey = new PublicKey(fromAddress)
|
|
69
|
-
|
|
70
|
-
// Set recipient address
|
|
71
|
-
const toAddress = 'RECIPIENT_SOLANA_ADDRESS'
|
|
72
|
-
const toPubkey = new PublicKey(toAddress)
|
|
73
|
-
|
|
74
|
-
// Connect to Solana network
|
|
75
|
-
const connection = new Connection('https://api.mainnet-beta.solana.com/')
|
|
76
|
-
|
|
77
|
-
// Get recent blockhash
|
|
78
|
-
const { blockhash } = await connection.getLatestBlockhash({
|
|
79
|
-
commitment: 'finalized'
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
// Create transfer instruction
|
|
83
|
-
const transferInstruction = SystemProgram.transfer({
|
|
84
|
-
fromPubkey,
|
|
85
|
-
toPubkey,
|
|
86
|
-
lamports: 1000 // 0.000001 SOL
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
// Create and setup transaction
|
|
90
|
-
const transaction = new Transaction().add(transferInstruction)
|
|
91
|
-
transaction.recentBlockhash = blockhash
|
|
92
|
-
transaction.feePayer = fromPubkey
|
|
93
|
-
|
|
94
|
-
// Serialize the transaction to base64
|
|
95
|
-
const serializedTransaction = transaction
|
|
96
|
-
.serialize({
|
|
97
|
-
requireAllSignatures: false,
|
|
98
|
-
verifySignatures: false
|
|
99
|
-
})
|
|
100
|
-
.toString('base64')
|
|
101
|
-
|
|
102
|
-
// Sign the transaction
|
|
103
|
-
const signature = await signer.signTransaction(serializedTransaction)
|
|
104
|
-
console.log('Transaction signature:', signature)
|
|
105
|
-
|
|
106
|
-
return signature
|
|
107
|
-
}
|
|
115
|
+
console.log('Auto approved:', withdrawal.auto_approved)
|
|
116
|
+
console.log('Withdrawal ID:', withdrawal.withdrawal.id)
|
|
117
|
+
console.log('Status:', withdrawal.withdrawal.status)
|
|
108
118
|
```
|
|
109
119
|
|
|
110
|
-
|
|
120
|
+
## Create Onchain Transaction
|
|
121
|
+
|
|
122
|
+
Sign and broadcast transactions directly on EVM or Solana networks using the built-in signers.
|
|
123
|
+
|
|
124
|
+
### EVM (Ethereum, Polygon, BSC, etc.)
|
|
111
125
|
|
|
112
126
|
```typescript
|
|
113
|
-
import { EtherSigner } from '@fystack/sdk'
|
|
127
|
+
import { EtherSigner, Environment } from '@fystack/sdk'
|
|
114
128
|
import { JsonRpcProvider, ethers } from 'ethers'
|
|
115
129
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
130
|
+
const signer = new EtherSigner(
|
|
131
|
+
{ apiKey: 'YOUR_API_KEY', apiSecret: 'YOUR_API_SECRET' },
|
|
132
|
+
Environment.Production
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
// Set the wallet to sign with
|
|
136
|
+
signer.setWallet('WALLET_ID')
|
|
137
|
+
|
|
138
|
+
// Connect to a provider and send a transaction
|
|
139
|
+
const provider = new JsonRpcProvider('YOUR_RPC_ENDPOINT')
|
|
140
|
+
const connectedSigner = signer.connect(provider)
|
|
141
|
+
|
|
142
|
+
const tx = await connectedSigner.sendTransaction({
|
|
143
|
+
to: '0xRecipientAddress',
|
|
144
|
+
value: ethers.parseEther('0.01')
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
console.log('Transaction hash:', tx.hash)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Solana
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
import { SolanaSigner, Environment } from '@fystack/sdk'
|
|
154
|
+
import { Connection, PublicKey, SystemProgram, Transaction } from '@solana/web3.js'
|
|
155
|
+
|
|
156
|
+
const signer = new SolanaSigner(
|
|
157
|
+
{ apiKey: 'YOUR_API_KEY', apiSecret: 'YOUR_API_SECRET' },
|
|
158
|
+
Environment.Production
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
const fromAddress = await signer.getAddress()
|
|
162
|
+
const fromPubkey = new PublicKey(fromAddress)
|
|
163
|
+
const toPubkey = new PublicKey('RECIPIENT_SOLANA_ADDRESS')
|
|
164
|
+
|
|
165
|
+
const connection = new Connection('https://api.mainnet-beta.solana.com/')
|
|
166
|
+
const { blockhash } = await connection.getLatestBlockhash({ commitment: 'finalized' })
|
|
119
167
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
168
|
+
const transaction = new Transaction().add(
|
|
169
|
+
SystemProgram.transfer({ fromPubkey, toPubkey, lamports: 1_000_000 })
|
|
170
|
+
)
|
|
171
|
+
transaction.recentBlockhash = blockhash
|
|
172
|
+
transaction.feePayer = fromPubkey
|
|
123
173
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
value: ethers.parseEther('0.0001') // Amount in ETH
|
|
128
|
-
})
|
|
174
|
+
const serialized = transaction
|
|
175
|
+
.serialize({ requireAllSignatures: false, verifySignatures: false })
|
|
176
|
+
.toString('base64')
|
|
129
177
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
178
|
+
const signature = await signer.signTransaction(serialized)
|
|
179
|
+
console.log('Transaction signature:', signature)
|
|
133
180
|
```
|
|
134
181
|
|
|
135
|
-
|
|
182
|
+
## Sweep Task
|
|
136
183
|
|
|
137
|
-
|
|
184
|
+
Automatically consolidate funds from multiple wallets into a central destination wallet on a recurring schedule.
|
|
138
185
|
|
|
139
186
|
```typescript
|
|
140
|
-
import {
|
|
141
|
-
|
|
187
|
+
import { SweepStrategy, SweepType, DestinationType } from '@fystack/sdk'
|
|
188
|
+
|
|
189
|
+
const task = await sdk.automation.createSweepTask({
|
|
190
|
+
name: 'Daily Consolidation',
|
|
191
|
+
strategy: SweepStrategy.Periodic,
|
|
192
|
+
frequencyInSeconds: 86400, // every 24 hours
|
|
193
|
+
minTriggerValueUsd: 50, // only sweep if wallet holds >= $50
|
|
194
|
+
destinationWalletId: 'CENTRAL_WALLET_UUID',
|
|
195
|
+
destinationType: DestinationType.InternalWallet,
|
|
196
|
+
walletIds: [
|
|
197
|
+
'WALLET_UUID_1',
|
|
198
|
+
'WALLET_UUID_2',
|
|
199
|
+
'WALLET_UUID_3'
|
|
200
|
+
],
|
|
201
|
+
// Optional: only sweep specific assets
|
|
202
|
+
assetIds: ['ASSET_UUID_1', 'ASSET_UUID_2'],
|
|
203
|
+
// Optional: keep a reserve in each source wallet
|
|
204
|
+
reserveType: ReserveType.FixedUsd,
|
|
205
|
+
reserveAmountUsd: 10 // keep $10 in each wallet
|
|
206
|
+
})
|
|
142
207
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
apiKey: 'YOUR_API_KEY',
|
|
146
|
-
environment: Environment.Production
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
// Create a checkout
|
|
150
|
-
const response = await paymentService.createCheckout({
|
|
151
|
-
price: '10.50',
|
|
152
|
-
currency: 'USD',
|
|
153
|
-
supported_assets: [
|
|
154
|
-
'SOL:1399811149', // Format: "ASSET:CHAIN_ID"
|
|
155
|
-
'USDC:1399811149'
|
|
156
|
-
],
|
|
157
|
-
description: 'Premium subscription package',
|
|
158
|
-
success_url: 'https://yourapp.com/payment/success',
|
|
159
|
-
cancel_url: 'https://yourapp.com/payment/cancel',
|
|
160
|
-
product_id: 'YOUR_PRODUCT_ID',
|
|
161
|
-
customer_id: 'YOUR_CUSTOMER_ID',
|
|
162
|
-
order_id: 'YOUR_ORDER_ID',
|
|
163
|
-
enable_localization: false,
|
|
164
|
-
destination_wallet_id: 'YOUR_DESTINATION_WALLET_ID',
|
|
165
|
-
expiry_duration_seconds: 3600 // 1 hour
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
console.log('Checkout created:', response.id)
|
|
169
|
-
|
|
170
|
-
// Get checkout details
|
|
171
|
-
const checkout = await paymentService.getCheckout(response.id)
|
|
172
|
-
|
|
173
|
-
// Create payment using the first supported asset
|
|
174
|
-
const payment = await paymentService.createCheckoutPayment(response.id, {
|
|
175
|
-
pay_asset_id: checkout.supported_assets[0].id
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
console.log('Payment created:', payment.id)
|
|
179
|
-
console.log('Send payment to:', payment.deposit_address)
|
|
180
|
-
|
|
181
|
-
// Get payment status
|
|
182
|
-
const paymentStatus = await paymentService.getCheckoutPayment(payment.id)
|
|
183
|
-
console.log('Payment status:', paymentStatus)
|
|
184
|
-
|
|
185
|
-
return payment
|
|
186
|
-
}
|
|
208
|
+
console.log('Sweep task ID:', task.id)
|
|
209
|
+
console.log('Enabled:', task.enabled)
|
|
187
210
|
```
|
|
188
211
|
|
|
189
|
-
|
|
212
|
+
## Webhook Verification
|
|
213
|
+
|
|
214
|
+
Verify incoming webhook signatures to ensure authenticity.
|
|
190
215
|
|
|
191
216
|
```typescript
|
|
192
|
-
import { APIService } from '@fystack/sdk'
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
217
|
+
import { APIService, Environment } from '@fystack/sdk'
|
|
218
|
+
|
|
219
|
+
const apiService = new APIService(
|
|
220
|
+
{ apiKey: 'YOUR_API_KEY', apiSecret: 'YOUR_API_SECRET' },
|
|
221
|
+
Environment.Production
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
const isValid = await apiService.Webhook.verifyEvent(event, signature)
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Payment Processing
|
|
228
|
+
|
|
229
|
+
Create checkouts and process crypto payments.
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
import { PaymentService, Environment } from '@fystack/sdk'
|
|
233
|
+
|
|
234
|
+
const paymentService = new PaymentService({
|
|
235
|
+
apiKey: 'YOUR_API_KEY',
|
|
236
|
+
environment: Environment.Production
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
const checkout = await paymentService.createCheckout({
|
|
240
|
+
price: '10.50',
|
|
241
|
+
currency: 'USD',
|
|
242
|
+
supported_assets: ['SOL:1399811149', 'USDC:1399811149'],
|
|
243
|
+
description: 'Premium subscription',
|
|
244
|
+
success_url: 'https://yourapp.com/success',
|
|
245
|
+
cancel_url: 'https://yourapp.com/cancel',
|
|
246
|
+
destination_wallet_id: 'YOUR_WALLET_ID',
|
|
247
|
+
expiry_duration_seconds: 3600
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
console.log('Checkout URL:', checkout.id)
|
|
206
251
|
```
|
package/src/api.ts
CHANGED
|
@@ -16,7 +16,9 @@ import {
|
|
|
16
16
|
WalletByWorkspaceResponse,
|
|
17
17
|
RequestWithdrawalParams,
|
|
18
18
|
RequestWithdrawalResponse,
|
|
19
|
-
WebhookPublicKeyResponse
|
|
19
|
+
WebhookPublicKeyResponse,
|
|
20
|
+
CreateSweepTaskParams,
|
|
21
|
+
SweepTaskResponse
|
|
20
22
|
} from './types'
|
|
21
23
|
import {
|
|
22
24
|
CreateCheckoutPayload,
|
|
@@ -264,6 +266,17 @@ export class APIService {
|
|
|
264
266
|
const response = await get(endpoint, headers)
|
|
265
267
|
return response.data
|
|
266
268
|
}
|
|
269
|
+
|
|
270
|
+
async createSweepTask(
|
|
271
|
+
workspaceId: string,
|
|
272
|
+
params: CreateSweepTaskParams
|
|
273
|
+
): Promise<SweepTaskResponse> {
|
|
274
|
+
const endpoint = this.API.endpoints.createSweepTask(workspaceId)
|
|
275
|
+
const transformedParams = transformCreateSweepTaskParams(params)
|
|
276
|
+
const headers = await composeAPIHeaders(this.credentials, 'POST', endpoint, transformedParams)
|
|
277
|
+
const response = await post(endpoint, transformedParams, headers)
|
|
278
|
+
return response.data
|
|
279
|
+
}
|
|
267
280
|
}
|
|
268
281
|
|
|
269
282
|
export class PaymentService {
|
|
@@ -422,6 +435,24 @@ export function transformRequestWithdrawalParams(data: RequestWithdrawalParams)
|
|
|
422
435
|
}
|
|
423
436
|
}
|
|
424
437
|
|
|
438
|
+
export function transformCreateSweepTaskParams(data: CreateSweepTaskParams) {
|
|
439
|
+
return {
|
|
440
|
+
name: data.name,
|
|
441
|
+
strategy: data.strategy,
|
|
442
|
+
min_trigger_value_usd: data.minTriggerValueUsd,
|
|
443
|
+
destination_wallet_id: data.destinationWalletId,
|
|
444
|
+
frequency_in_seconds: data.frequencyInSeconds,
|
|
445
|
+
wallet_ids: data.walletIds,
|
|
446
|
+
...(data.sweepType !== undefined && { sweep_type: data.sweepType }),
|
|
447
|
+
...(data.destinationType !== undefined && { destination_type: data.destinationType }),
|
|
448
|
+
...(data.assetIds !== undefined && { asset_ids: data.assetIds }),
|
|
449
|
+
...(data.reserveType !== undefined && { reserve_type: data.reserveType }),
|
|
450
|
+
...(data.reserveAmountUsd !== undefined && { reserve_amount_usd: data.reserveAmountUsd }),
|
|
451
|
+
...(data.reservePercentageUsd !== undefined && { reserve_percentage_usd: data.reservePercentageUsd }),
|
|
452
|
+
...(data.enabled !== undefined && { enabled: data.enabled })
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
425
456
|
;(BigInt.prototype as any).toJSON = function () {
|
|
426
457
|
return this.toString()
|
|
427
458
|
}
|
package/src/config.ts
CHANGED
|
@@ -23,6 +23,7 @@ export interface APIEndpoints {
|
|
|
23
23
|
rescanTransaction: () => string
|
|
24
24
|
requestWithdrawal: (walletId: string) => string
|
|
25
25
|
getWebhookPublicKey: (workspaceId: string) => string
|
|
26
|
+
createSweepTask: (workspaceId: string) => string
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
const getBaseURL = (env: Environment): string => {
|
|
@@ -32,7 +33,7 @@ const getBaseURL = (env: Environment): string => {
|
|
|
32
33
|
case Environment.Sandbox:
|
|
33
34
|
return 'https://api-dev.fystack.io'
|
|
34
35
|
case Environment.Production:
|
|
35
|
-
return 'https://
|
|
36
|
+
return 'https://fystack.excelon.io'
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -74,8 +75,12 @@ const createAPI = (env: Environment): APIConfig => {
|
|
|
74
75
|
getDepositAddress: (walletId: string, addressType: string) =>
|
|
75
76
|
withBaseURL(`/wallets/${walletId}/deposit-address?address_type=${addressType}`),
|
|
76
77
|
rescanTransaction: () => withBaseURL('/networks/rescan-transaction'),
|
|
77
|
-
requestWithdrawal: (walletId: string) =>
|
|
78
|
-
|
|
78
|
+
requestWithdrawal: (walletId: string) =>
|
|
79
|
+
withBaseURL(`/wallets/${walletId}/request-withdrawal`),
|
|
80
|
+
getWebhookPublicKey: (workspaceId: string) =>
|
|
81
|
+
withBaseURL(`/workspaces/${workspaceId}/webhook-verification-key`),
|
|
82
|
+
createSweepTask: (workspaceId: string) =>
|
|
83
|
+
withBaseURL(`/workspaces/${workspaceId}/automation/sweep-task`)
|
|
79
84
|
}
|
|
80
85
|
}
|
|
81
86
|
}
|
package/src/enum.ts
CHANGED
|
@@ -60,3 +60,17 @@ export enum WithdrawalStatus {
|
|
|
60
60
|
Completed = 'completed',
|
|
61
61
|
Failed = 'failed'
|
|
62
62
|
}
|
|
63
|
+
|
|
64
|
+
export enum SweepStrategy {
|
|
65
|
+
Periodic = 'periodic'
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export enum SweepType {
|
|
69
|
+
Default = 'default',
|
|
70
|
+
PaymentLink = 'payment_link',
|
|
71
|
+
Checkout = 'checkout'
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export enum ReserveType {
|
|
75
|
+
FixedUsd = 'fixed_usd'
|
|
76
|
+
}
|
package/src/sdk.ts
CHANGED
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
WalletByWorkspaceResponse,
|
|
13
13
|
RequestWithdrawalParams,
|
|
14
14
|
RequestWithdrawalResponse,
|
|
15
|
-
WebhookPublicKeyResponse
|
|
15
|
+
WebhookPublicKeyResponse,
|
|
16
|
+
CreateSweepTaskParams,
|
|
17
|
+
SweepTaskResponse
|
|
16
18
|
} from './types'
|
|
17
19
|
import { validateUUID } from './utils'
|
|
18
20
|
import { AddressType, WalletCreationStatus, WalletType } from './enum'
|
|
@@ -21,28 +23,32 @@ export interface SDKOptions {
|
|
|
21
23
|
credentials: APICredentials
|
|
22
24
|
workspaceId?: string
|
|
23
25
|
environment?: Environment
|
|
24
|
-
|
|
26
|
+
/** Enable debug logging. Defaults to false */
|
|
27
|
+
debug?: boolean
|
|
25
28
|
}
|
|
26
29
|
|
|
27
30
|
export class FystackSDK {
|
|
28
31
|
private apiService: APIService
|
|
29
|
-
private
|
|
32
|
+
private debugEnabled: boolean
|
|
30
33
|
private workspaceId?: string
|
|
31
34
|
|
|
35
|
+
public automation: AutomationNamespace
|
|
36
|
+
|
|
32
37
|
constructor(options: SDKOptions) {
|
|
33
38
|
const {
|
|
34
39
|
credentials,
|
|
35
40
|
workspaceId,
|
|
36
41
|
environment = Environment.Production,
|
|
37
|
-
|
|
42
|
+
debug = false
|
|
38
43
|
} = options
|
|
39
44
|
this.apiService = new APIService(credentials, environment)
|
|
40
|
-
this.
|
|
45
|
+
this.debugEnabled = debug
|
|
41
46
|
this.workspaceId = workspaceId
|
|
47
|
+
this.automation = new AutomationNamespace(this)
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
private log(message: string): void {
|
|
45
|
-
if (this.
|
|
51
|
+
if (this.debugEnabled) {
|
|
46
52
|
console.log(`[FystackSDK] ${message}`)
|
|
47
53
|
}
|
|
48
54
|
}
|
|
@@ -235,4 +241,49 @@ export class FystackSDK {
|
|
|
235
241
|
const response = await this.apiService.getWebhookPublicKey(workspaceId)
|
|
236
242
|
return response
|
|
237
243
|
}
|
|
244
|
+
|
|
245
|
+
/** @internal */
|
|
246
|
+
_getApiService(): APIService {
|
|
247
|
+
return this.apiService
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** @internal */
|
|
251
|
+
_log(message: string): void {
|
|
252
|
+
this.log(message)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** @internal */
|
|
256
|
+
_getWorkspaceId(): string {
|
|
257
|
+
if (!this.workspaceId) {
|
|
258
|
+
throw new Error('Workspace ID is required. Please set workspaceId in the constructor.')
|
|
259
|
+
}
|
|
260
|
+
return this.workspaceId
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
class AutomationNamespace {
|
|
265
|
+
private sdk: FystackSDK
|
|
266
|
+
|
|
267
|
+
constructor(sdk: FystackSDK) {
|
|
268
|
+
this.sdk = sdk
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async createSweepTask(params: CreateSweepTaskParams): Promise<SweepTaskResponse> {
|
|
272
|
+
const workspaceId = this.sdk._getWorkspaceId()
|
|
273
|
+
|
|
274
|
+
validateUUID(params.destinationWalletId, 'destinationWalletId')
|
|
275
|
+
for (const walletId of params.walletIds) {
|
|
276
|
+
validateUUID(walletId, 'walletIds')
|
|
277
|
+
}
|
|
278
|
+
if (params.assetIds) {
|
|
279
|
+
for (const assetId of params.assetIds) {
|
|
280
|
+
validateUUID(assetId, 'assetIds')
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
this.sdk._log(`Creating sweep task "${params.name}" for workspace ${workspaceId}`)
|
|
285
|
+
const response = await this.sdk._getApiService().createSweepTask(workspaceId, params)
|
|
286
|
+
this.sdk._log(`Sweep task created with ID: ${response.id}`)
|
|
287
|
+
return response
|
|
288
|
+
}
|
|
238
289
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { SweepTaskParams } from './api'
|
|
2
2
|
import {
|
|
3
|
+
DestinationType,
|
|
4
|
+
ReserveType,
|
|
5
|
+
SweepStrategy,
|
|
6
|
+
SweepType,
|
|
3
7
|
TxApprovalStatus,
|
|
4
8
|
TxStatus,
|
|
5
9
|
WalletCreationStatus,
|
|
@@ -231,3 +235,55 @@ export interface RequestWithdrawalResponse {
|
|
|
231
235
|
export interface WebhookPublicKeyResponse {
|
|
232
236
|
public_key: string // base64 encoded ed25519 public key
|
|
233
237
|
}
|
|
238
|
+
|
|
239
|
+
export interface CreateSweepTaskParams {
|
|
240
|
+
/** Display name for the sweep task */
|
|
241
|
+
name: string
|
|
242
|
+
/** Sweep execution strategy */
|
|
243
|
+
strategy: SweepStrategy
|
|
244
|
+
/** Minimum USD value in a wallet to trigger a sweep */
|
|
245
|
+
minTriggerValueUsd: number
|
|
246
|
+
/** UUID of the destination wallet or address book record that receives swept funds */
|
|
247
|
+
destinationWalletId: string
|
|
248
|
+
/** How often (in seconds) the sweep task checks wallet balances */
|
|
249
|
+
frequencyInSeconds: number
|
|
250
|
+
/** List of wallet UUIDs to sweep from */
|
|
251
|
+
walletIds: string[]
|
|
252
|
+
/** Type of sweep task. Defaults to "default" */
|
|
253
|
+
sweepType?: SweepType
|
|
254
|
+
/** Whether the destination is an internal wallet or an address book entry. Defaults to "internal_wallet" */
|
|
255
|
+
destinationType?: DestinationType
|
|
256
|
+
/** Optional list of specific asset UUIDs to sweep. If omitted, all assets are swept */
|
|
257
|
+
assetIds?: string[]
|
|
258
|
+
/** Reserve strategy type (e.g. keep a fixed USD amount in the source wallet) */
|
|
259
|
+
reserveType?: ReserveType
|
|
260
|
+
/** Fixed USD amount to reserve in each source wallet (used when reserveType is "fixed_usd") */
|
|
261
|
+
reserveAmountUsd?: number
|
|
262
|
+
/** Percentage of USD value to reserve in each source wallet */
|
|
263
|
+
reservePercentageUsd?: number
|
|
264
|
+
/** Whether the task is enabled. Defaults to true */
|
|
265
|
+
enabled?: boolean
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface SweepTaskResponse {
|
|
269
|
+
id: string
|
|
270
|
+
created_at: string
|
|
271
|
+
updated_at: string
|
|
272
|
+
name: string
|
|
273
|
+
workspace_id: string
|
|
274
|
+
strategy: string
|
|
275
|
+
min_trigger_value_usd: string
|
|
276
|
+
destination_wallet_id: string
|
|
277
|
+
frequency_in_seconds: number
|
|
278
|
+
gas_tank_wallet_id: string
|
|
279
|
+
last_executed_at: string | null
|
|
280
|
+
is_executing: boolean
|
|
281
|
+
enabled: boolean
|
|
282
|
+
created_by_user_id: string
|
|
283
|
+
sweep_type: string
|
|
284
|
+
destination_type: string
|
|
285
|
+
deviation_rate: string
|
|
286
|
+
reserve_type?: string
|
|
287
|
+
reserve_amount_usd?: string
|
|
288
|
+
reserve_percentage_usd?: string
|
|
289
|
+
}
|