@fystack/sdk 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +111 -54
- package/dist/index.d.cts +318 -269
- package/dist/index.d.mts +318 -269
- package/dist/index.esm.d.ts +318 -269
- package/dist/index.esm.js +111 -55
- package/dist/index.mjs +111 -55
- package/dist/types/index.d.ts +318 -269
- package/package.json +1 -1
- package/readme.md +7 -1
- package/src/api.ts +42 -13
- package/src/config.ts +4 -2
- package/src/enum.ts +46 -0
- package/src/index.ts +1 -0
- package/src/sdk.ts +31 -7
- package/src/signer.ts +4 -3
- package/src/solanaSigner.ts +4 -3
- package/src/types.ts +11 -30
- package/test.js +0 -76
package/src/api.ts
CHANGED
|
@@ -10,10 +10,9 @@ import {
|
|
|
10
10
|
TransactionStatusResponse,
|
|
11
11
|
CreateWalletResponse,
|
|
12
12
|
WalletCreationStatusResponse,
|
|
13
|
-
WalletType,
|
|
14
13
|
WalletAsset,
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
DepositAddressResponse,
|
|
15
|
+
RescanTransactionParams
|
|
17
16
|
} from './types'
|
|
18
17
|
import {
|
|
19
18
|
CreateCheckoutPayload,
|
|
@@ -23,6 +22,7 @@ import {
|
|
|
23
22
|
GetCheckoutPaymentResponse,
|
|
24
23
|
GetCheckoutResponse
|
|
25
24
|
} from './payment'
|
|
25
|
+
import { AddressType, DestinationType, WalletPurpose, WalletType } from './enum'
|
|
26
26
|
|
|
27
27
|
interface APIResponse {
|
|
28
28
|
data: any
|
|
@@ -45,9 +45,18 @@ export interface WalletDetail {
|
|
|
45
45
|
Address: string
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
export interface SweepTaskParams {
|
|
49
|
+
minTriggerValueUsd: number
|
|
50
|
+
destinationWalletId: string
|
|
51
|
+
destinationType: DestinationType
|
|
52
|
+
}
|
|
53
|
+
|
|
48
54
|
export interface CreateWalletPayload {
|
|
49
55
|
name: string
|
|
50
56
|
walletType: WalletType
|
|
57
|
+
walletPurpose?: WalletPurpose
|
|
58
|
+
sweepTaskParams?: SweepTaskParams
|
|
59
|
+
sweepTaskId?: string
|
|
51
60
|
}
|
|
52
61
|
|
|
53
62
|
export interface PaymentServiceParams {
|
|
@@ -55,11 +64,6 @@ export interface PaymentServiceParams {
|
|
|
55
64
|
environment: Environment
|
|
56
65
|
}
|
|
57
66
|
|
|
58
|
-
export enum WalletAddressType {
|
|
59
|
-
Evm = 'evm',
|
|
60
|
-
Sol = 'sol'
|
|
61
|
-
}
|
|
62
|
-
|
|
63
67
|
async function composeAPIHeaders(
|
|
64
68
|
credentials: APICredentials,
|
|
65
69
|
httpMethod: string,
|
|
@@ -109,10 +113,7 @@ export class APIService {
|
|
|
109
113
|
this.API = createAPI(environment)
|
|
110
114
|
}
|
|
111
115
|
|
|
112
|
-
async getWalletDetail(
|
|
113
|
-
addressType: WalletAddressType = WalletAddressType.Evm,
|
|
114
|
-
walletId?: string
|
|
115
|
-
): Promise<WalletDetail> {
|
|
116
|
+
async getWalletDetail(addressType = AddressType.Evm, walletId?: string): Promise<WalletDetail> {
|
|
116
117
|
const endpoint = this.API.endpoints.getWalletDetail(walletId)
|
|
117
118
|
const headers = await composeAPIHeaders(this.credentials, 'GET', endpoint)
|
|
118
119
|
console.info('headers', headers)
|
|
@@ -201,6 +202,18 @@ export class APIService {
|
|
|
201
202
|
const response = await get(endpoint, headers)
|
|
202
203
|
return response.data
|
|
203
204
|
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Rescans a transaction on a specific network
|
|
208
|
+
* @param params Transaction hash and network ID
|
|
209
|
+
* @returns API response
|
|
210
|
+
*/
|
|
211
|
+
async rescanTransaction(params: RescanTransactionParams): Promise<void> {
|
|
212
|
+
const endpoint = this.API.endpoints.rescanTransaction()
|
|
213
|
+
const transformedParams = transformRescanTransactionParams(params)
|
|
214
|
+
const headers = await composeAPIHeaders(this.credentials, 'POST', endpoint, transformedParams)
|
|
215
|
+
await post(endpoint, transformedParams, headers)
|
|
216
|
+
}
|
|
204
217
|
}
|
|
205
218
|
|
|
206
219
|
export class PaymentService {
|
|
@@ -329,7 +342,23 @@ export function transformWalletDetail(data: Record<string, string>): WalletDetai
|
|
|
329
342
|
export function transformCreateWalletPayload(data: CreateWalletPayload) {
|
|
330
343
|
return {
|
|
331
344
|
name: data.name,
|
|
332
|
-
wallet_type: data.walletType
|
|
345
|
+
wallet_type: data.walletType,
|
|
346
|
+
...(data.walletPurpose !== undefined && { wallet_purpose: data.walletPurpose }),
|
|
347
|
+
...(data.sweepTaskParams !== undefined && {
|
|
348
|
+
sweep_task_params: {
|
|
349
|
+
min_trigger_value_usd: data.sweepTaskParams?.minTriggerValueUsd,
|
|
350
|
+
destination_wallet_id: data.sweepTaskParams?.destinationWalletId,
|
|
351
|
+
destination_type: data.sweepTaskParams?.destinationType
|
|
352
|
+
}
|
|
353
|
+
}),
|
|
354
|
+
...(data.sweepTaskId !== undefined && { sweep_task_id: data.sweepTaskId })
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export function transformRescanTransactionParams(data: RescanTransactionParams) {
|
|
359
|
+
return {
|
|
360
|
+
tx_hash: data.txHash,
|
|
361
|
+
network_id: data.networkId
|
|
333
362
|
}
|
|
334
363
|
}
|
|
335
364
|
|
package/src/config.ts
CHANGED
|
@@ -19,6 +19,7 @@ export interface APIEndpoints {
|
|
|
19
19
|
getWalletCreationStatus: (walletId: string) => string
|
|
20
20
|
getWalletAssets: (walletId: string) => string
|
|
21
21
|
getDepositAddress: (walletId: string, addressType: string) => string
|
|
22
|
+
rescanTransaction: () => string
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
const getBaseURL = (env: Environment): string => {
|
|
@@ -26,7 +27,7 @@ const getBaseURL = (env: Environment): string => {
|
|
|
26
27
|
case Environment.Local:
|
|
27
28
|
return 'http://localhost:8150'
|
|
28
29
|
case Environment.Sandbox:
|
|
29
|
-
return 'https://
|
|
30
|
+
return 'https://api-dev.fystack.io'
|
|
30
31
|
case Environment.Production:
|
|
31
32
|
return 'https://api.fystack.io'
|
|
32
33
|
}
|
|
@@ -67,7 +68,8 @@ const createAPI = (env: Environment): APIConfig => {
|
|
|
67
68
|
withBaseURL(`/wallets/creation-status/${walletId}`),
|
|
68
69
|
getWalletAssets: (walletId: string) => withBaseURL(`/wallets/${walletId}/assets`),
|
|
69
70
|
getDepositAddress: (walletId: string, addressType: string) =>
|
|
70
|
-
withBaseURL(`/wallets/${walletId}/deposit-address?address_type=${addressType}`)
|
|
71
|
+
withBaseURL(`/wallets/${walletId}/deposit-address?address_type=${addressType}`),
|
|
72
|
+
rescanTransaction: () => withBaseURL('/networks/rescan-transaction')
|
|
71
73
|
}
|
|
72
74
|
}
|
|
73
75
|
}
|
package/src/enum.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Wallets
|
|
2
|
+
export enum WalletType {
|
|
3
|
+
Standard = 'standard',
|
|
4
|
+
MPC = 'mpc'
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export enum WalletPurpose {
|
|
8
|
+
General = 'general',
|
|
9
|
+
Gastank = 'gas_tank',
|
|
10
|
+
Deployment = 'deployment',
|
|
11
|
+
Custody = 'custody',
|
|
12
|
+
User = 'user',
|
|
13
|
+
Payment = 'payment'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export enum WalletCreationStatus {
|
|
17
|
+
Pending = 'pending',
|
|
18
|
+
Success = 'success',
|
|
19
|
+
Error = 'error'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export enum AddressType {
|
|
23
|
+
Evm = 'evm',
|
|
24
|
+
Solana = 'sol',
|
|
25
|
+
Tron = 'tron'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export enum DestinationType {
|
|
29
|
+
InternalWallet = 'internal_wallet',
|
|
30
|
+
AddressBook = 'address_book'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export enum TxStatus {
|
|
34
|
+
Pending = 'pending',
|
|
35
|
+
Completed = 'completed',
|
|
36
|
+
Confirmed = 'confirmed',
|
|
37
|
+
Failed = 'failed',
|
|
38
|
+
PendingApproval = 'pending_approval',
|
|
39
|
+
Rejected = 'rejected'
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export enum TxApprovalStatus {
|
|
43
|
+
Pending = 'pending',
|
|
44
|
+
Approved = 'approved',
|
|
45
|
+
Rejected = 'rejected'
|
|
46
|
+
}
|
package/src/index.ts
CHANGED
package/src/sdk.ts
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { APIService } from './api'
|
|
2
|
-
import { APICredentials, CreateWalletOptions } from './types'
|
|
3
2
|
import { Environment } from './config'
|
|
4
3
|
import { StatusPoller } from './utils/statusPoller'
|
|
5
4
|
import {
|
|
6
|
-
WalletCreationStatus,
|
|
7
5
|
CreateWalletResponse,
|
|
8
6
|
WalletCreationStatusResponse,
|
|
9
|
-
WalletType,
|
|
10
7
|
WalletAsset,
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
DepositAddressResponse,
|
|
9
|
+
APICredentials,
|
|
10
|
+
CreateWalletOptions,
|
|
11
|
+
RescanTransactionParams
|
|
13
12
|
} from './types'
|
|
14
13
|
import { validateUUID } from './utils'
|
|
14
|
+
import { AddressType, WalletCreationStatus, WalletType } from './enum'
|
|
15
15
|
|
|
16
16
|
export interface SDKOptions {
|
|
17
17
|
credentials: APICredentials
|
|
@@ -45,11 +45,20 @@ export class FystackSDK {
|
|
|
45
45
|
options: CreateWalletOptions,
|
|
46
46
|
waitForCompletion: boolean = true
|
|
47
47
|
): Promise<CreateWalletResponse> {
|
|
48
|
-
const {
|
|
48
|
+
const {
|
|
49
|
+
name,
|
|
50
|
+
walletType = WalletType.Standard,
|
|
51
|
+
sweepTaskParams,
|
|
52
|
+
walletPurpose,
|
|
53
|
+
sweepTaskId
|
|
54
|
+
} = options
|
|
49
55
|
|
|
50
56
|
const response = await this.apiService.createWallet({
|
|
51
57
|
name,
|
|
52
|
-
walletType
|
|
58
|
+
walletType,
|
|
59
|
+
walletPurpose,
|
|
60
|
+
sweepTaskParams,
|
|
61
|
+
sweepTaskId
|
|
53
62
|
})
|
|
54
63
|
|
|
55
64
|
if (waitForCompletion && response.status === WalletCreationStatus.Pending) {
|
|
@@ -137,4 +146,19 @@ export class FystackSDK {
|
|
|
137
146
|
const depositAddressInfo = await this.apiService.getDepositAddress(walletId, addressType)
|
|
138
147
|
return depositAddressInfo
|
|
139
148
|
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Rescans a transaction on a specific network
|
|
152
|
+
* @param params Transaction hash and network ID
|
|
153
|
+
* @returns Promise that resolves when the rescan is initiated
|
|
154
|
+
*/
|
|
155
|
+
async rescanTransaction(params: RescanTransactionParams): Promise<void> {
|
|
156
|
+
validateUUID(params.networkId, 'networkId')
|
|
157
|
+
|
|
158
|
+
if (!params.txHash || params.txHash.trim() === '') {
|
|
159
|
+
throw new Error('Invalid transaction hash provided')
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
await this.apiService.rescanTransaction(params)
|
|
163
|
+
}
|
|
140
164
|
}
|
package/src/signer.ts
CHANGED
|
@@ -15,10 +15,11 @@ import {
|
|
|
15
15
|
Signature
|
|
16
16
|
} from 'ethers'
|
|
17
17
|
import { TransactionRequest } from 'ethers/src.ts/providers'
|
|
18
|
-
import { APIService, WalletDetail
|
|
19
|
-
import { APICredentials, TransactionStatusResponse,
|
|
18
|
+
import { APIService, WalletDetail } from './api'
|
|
19
|
+
import { APICredentials, TransactionStatusResponse, TransactionError } from './types'
|
|
20
20
|
import { Environment } from './config'
|
|
21
21
|
import { StatusPoller, StatusPollerOptions } from './utils/statusPoller'
|
|
22
|
+
import { AddressType, TxStatus } from './enum'
|
|
22
23
|
|
|
23
24
|
export class EtherSigner extends AbstractSigner {
|
|
24
25
|
private address!: string
|
|
@@ -73,7 +74,7 @@ export class EtherSigner extends AbstractSigner {
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
const detail: WalletDetail = await this.APIService.getWalletDetail(
|
|
76
|
-
|
|
77
|
+
AddressType.Evm,
|
|
77
78
|
this.walletDetail?.WalletID
|
|
78
79
|
)
|
|
79
80
|
|
package/src/solanaSigner.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { APIService,
|
|
2
|
-
import { APICredentials, TransactionStatusResponse,
|
|
1
|
+
import { APIService, WalletDetail } from './api'
|
|
2
|
+
import { APICredentials, TransactionStatusResponse, TransactionError } from './types'
|
|
3
3
|
import { Environment } from './config'
|
|
4
4
|
import { StatusPoller, StatusPollerOptions } from './utils/statusPoller'
|
|
5
5
|
import { Transaction, PublicKey, VersionedTransaction } from '@solana/web3.js'
|
|
6
6
|
import bs58 from 'bs58'
|
|
7
7
|
import { Buffer } from 'buffer'
|
|
8
|
+
import { AddressType, TxStatus } from './enum'
|
|
8
9
|
|
|
9
10
|
export class SolanaSigner {
|
|
10
11
|
private address!: string
|
|
@@ -56,7 +57,7 @@ export class SolanaSigner {
|
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
const detail: WalletDetail = await this.APIService.getWalletDetail(
|
|
59
|
-
|
|
60
|
+
AddressType.Solana,
|
|
60
61
|
this.walletDetail?.WalletID
|
|
61
62
|
)
|
|
62
63
|
|
package/src/types.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { SweepTaskParams } from './api'
|
|
2
|
+
import { TxApprovalStatus, TxStatus, WalletCreationStatus, WalletPurpose, WalletType } from './enum'
|
|
3
|
+
|
|
1
4
|
export class TransactionError extends Error {
|
|
2
5
|
constructor(
|
|
3
6
|
message: string,
|
|
@@ -9,20 +12,6 @@ export class TransactionError extends Error {
|
|
|
9
12
|
this.name = 'TransactionError'
|
|
10
13
|
}
|
|
11
14
|
}
|
|
12
|
-
export enum TxStatus {
|
|
13
|
-
Pending = 'pending',
|
|
14
|
-
Completed = 'completed',
|
|
15
|
-
Confirmed = 'confirmed',
|
|
16
|
-
Failed = 'failed',
|
|
17
|
-
PendingApproval = 'pending_approval',
|
|
18
|
-
Rejected = 'rejected'
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export enum TxApprovalStatus {
|
|
22
|
-
Pending = 'pending',
|
|
23
|
-
Approved = 'approved',
|
|
24
|
-
Rejected = 'rejected'
|
|
25
|
-
}
|
|
26
15
|
|
|
27
16
|
export interface APICredentials {
|
|
28
17
|
apiKey: string
|
|
@@ -79,20 +68,12 @@ export interface TransactionStatusResponse {
|
|
|
79
68
|
failed_reason?: string
|
|
80
69
|
}
|
|
81
70
|
|
|
82
|
-
// Wallets
|
|
83
|
-
export enum WalletType {
|
|
84
|
-
Standard = 'standard',
|
|
85
|
-
MPC = 'mpc'
|
|
86
|
-
}
|
|
87
|
-
|
|
88
71
|
export interface CreateWalletOptions {
|
|
89
72
|
name: string
|
|
90
73
|
walletType: WalletType
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
Success = 'success',
|
|
95
|
-
Error = 'error'
|
|
74
|
+
walletPurpose?: WalletPurpose
|
|
75
|
+
sweepTaskParams?: SweepTaskParams
|
|
76
|
+
sweepTaskId?: string
|
|
96
77
|
}
|
|
97
78
|
|
|
98
79
|
export interface CreateWalletResponse {
|
|
@@ -152,13 +133,13 @@ export interface WalletAsset {
|
|
|
152
133
|
asset: WalletAssetDetail
|
|
153
134
|
}
|
|
154
135
|
|
|
155
|
-
export enum AddressType {
|
|
156
|
-
Evm = 'evm',
|
|
157
|
-
Solana = 'sol'
|
|
158
|
-
}
|
|
159
|
-
|
|
160
136
|
export interface DepositAddressResponse {
|
|
161
137
|
asset_id?: string
|
|
162
138
|
address: string
|
|
163
139
|
qr_code: string
|
|
164
140
|
}
|
|
141
|
+
|
|
142
|
+
export interface RescanTransactionParams {
|
|
143
|
+
txHash: string
|
|
144
|
+
networkId: string
|
|
145
|
+
}
|
package/test.js
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { TypedDataEncoder, verifyTypedData, Signature } from 'ethers'
|
|
2
|
-
|
|
3
|
-
// 0x2f71f2595162eaca40708bf6d6327d437e760b27d26f3a933389ebdb4eedf3b167008df6f1d403503c82a6d58da5659b14c578019603d6b138b2c03729c92af701
|
|
4
|
-
// 0xd77d10c530b25d1ea6a466eb2b3169138b5ca0d1320ff54bbad000d97f686d0a314c5233844d84da5adf3580afa38c82d9595c22a985acfea02ca722c55df48a00
|
|
5
|
-
// Example usage
|
|
6
|
-
const address = '0xFFe120Fd4D5AB5A9f25b25c30620ac8ee3E1EF21'
|
|
7
|
-
const jsonData = {
|
|
8
|
-
domain: {
|
|
9
|
-
name: 'Permit2',
|
|
10
|
-
chainId: '8453',
|
|
11
|
-
verifyingContract: '0x000000000022d473030f116ddee9f6b43ac78ba3'
|
|
12
|
-
},
|
|
13
|
-
types: {
|
|
14
|
-
PermitSingle: [
|
|
15
|
-
{ name: 'details', type: 'PermitDetails' },
|
|
16
|
-
{ name: 'spender', type: 'address' },
|
|
17
|
-
{ name: 'sigDeadline', type: 'uint256' }
|
|
18
|
-
],
|
|
19
|
-
PermitDetails: [
|
|
20
|
-
{ name: 'token', type: 'address' },
|
|
21
|
-
{ name: 'amount', type: 'uint160' },
|
|
22
|
-
{ name: 'expiration', type: 'uint48' },
|
|
23
|
-
{ name: 'nonce', type: 'uint48' }
|
|
24
|
-
]
|
|
25
|
-
},
|
|
26
|
-
message: {
|
|
27
|
-
details: {
|
|
28
|
-
token: '0x0b3e328455c4059eeb9e3f84b5543f74e24e7e1b',
|
|
29
|
-
amount: '1461501637330902918203684832716283019655932542975',
|
|
30
|
-
expiration: '1743496074',
|
|
31
|
-
nonce: '0'
|
|
32
|
-
},
|
|
33
|
-
spender: '0x6ff5693b99212da76ad316178a184ab56d299b43',
|
|
34
|
-
sigDeadline: '1740905874'
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
const signature =
|
|
38
|
-
'0x032f29648f9c2d9d2524aef755c225b96121f2c9b01beee5869a70ef95eb089548dc41f71126dac83c1632738dbea12bf5c925715068e32dda0064701bfc019e00'
|
|
39
|
-
|
|
40
|
-
async function verifySignature(address, jsonData, signature) {
|
|
41
|
-
try {
|
|
42
|
-
// Step 1: Compute the EIP-712 hash
|
|
43
|
-
const computedHash = TypedDataEncoder.hash(jsonData.domain, jsonData.types, jsonData.message)
|
|
44
|
-
console.log('🔹 Computed EIP-712 Hash:', computedHash)
|
|
45
|
-
|
|
46
|
-
// Step 2: Recover the signer address
|
|
47
|
-
const recoveredAddress = verifyTypedData(
|
|
48
|
-
jsonData.domain,
|
|
49
|
-
jsonData.types,
|
|
50
|
-
jsonData.message,
|
|
51
|
-
signature
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
console.log('✅ Recovered Address:', recoveredAddress)
|
|
55
|
-
console.log('🔹 Expected Address:', address)
|
|
56
|
-
|
|
57
|
-
// Step 3: Compare the addresses
|
|
58
|
-
const isValid = recoveredAddress.toLowerCase() === address.toLowerCase()
|
|
59
|
-
console.log('🔹 Is Signature Valid?', isValid)
|
|
60
|
-
|
|
61
|
-
// Step 4: Debug signature parts (r, s, v)
|
|
62
|
-
const sig = Signature.from(signature)
|
|
63
|
-
console.log('🔹 Signature Parts:')
|
|
64
|
-
console.log(' r:', sig.r)
|
|
65
|
-
console.log(' s:', sig.s)
|
|
66
|
-
console.log(' v:', sig.v)
|
|
67
|
-
|
|
68
|
-
return isValid
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error('❌ Signature Verification Failed:', error)
|
|
71
|
-
return false
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Run verification
|
|
76
|
-
verifySignature(address, jsonData, signature)
|