@fystack/sdk 0.1.1 → 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/src/api.ts CHANGED
@@ -10,10 +10,9 @@ import {
10
10
  TransactionStatusResponse,
11
11
  CreateWalletResponse,
12
12
  WalletCreationStatusResponse,
13
- WalletType,
14
13
  WalletAsset,
15
- AddressType,
16
- DepositAddressResponse
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,
@@ -67,7 +71,13 @@ async function composeAPIHeaders(
67
71
  body: Record<string, any> = {}
68
72
  ): Promise<Record<string, string>> {
69
73
  if (credentials.apiSecret == '') {
70
- // If APISecret is not provided, fallback to cookie mode with no headers
74
+ // If APISecret is not provided, use authToken
75
+ if (credentials.authToken) {
76
+ return {
77
+ Authorization: credentials.authToken
78
+ }
79
+ }
80
+ // fallback to cookie mode with no headers
71
81
  return {}
72
82
  }
73
83
 
@@ -103,10 +113,7 @@ export class APIService {
103
113
  this.API = createAPI(environment)
104
114
  }
105
115
 
106
- async getWalletDetail(
107
- addressType: WalletAddressType = WalletAddressType.Evm,
108
- walletId?: string
109
- ): Promise<WalletDetail> {
116
+ async getWalletDetail(addressType = AddressType.Evm, walletId?: string): Promise<WalletDetail> {
110
117
  const endpoint = this.API.endpoints.getWalletDetail(walletId)
111
118
  const headers = await composeAPIHeaders(this.credentials, 'GET', endpoint)
112
119
  console.info('headers', headers)
@@ -195,6 +202,18 @@ export class APIService {
195
202
  const response = await get(endpoint, headers)
196
203
  return response.data
197
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
+ }
198
217
  }
199
218
 
200
219
  export class PaymentService {
@@ -323,7 +342,23 @@ export function transformWalletDetail(data: Record<string, string>): WalletDetai
323
342
  export function transformCreateWalletPayload(data: CreateWalletPayload) {
324
343
  return {
325
344
  name: data.name,
326
- 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
327
362
  }
328
363
  }
329
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://apex.void.exchange'
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
@@ -3,5 +3,6 @@ export * from './signer'
3
3
  export * from './solanaSigner'
4
4
  export * from './api'
5
5
  export * from './types'
6
+ export * from './enum'
6
7
  export * from './config'
7
8
  export * from './utils/statusPoller'
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
- AddressType,
12
- DepositAddressResponse
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 { name, walletType = WalletType.Standard } = options
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, WalletAddressType } from './api'
19
- import { APICredentials, TransactionStatusResponse, TxStatus, TransactionError } from './types'
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
@@ -64,12 +65,16 @@ export class EtherSigner extends AbstractSigner {
64
65
  return this.address
65
66
  }
66
67
 
67
- if (!this.APICredentials.apiKey && !this.walletDetail.WalletID) {
68
+ if (
69
+ !this.APICredentials.apiKey &&
70
+ !this.APICredentials.authToken &&
71
+ !this.walletDetail.WalletID
72
+ ) {
68
73
  throw new Error('Wallet detail not found, use setWallet(walletId) to set wallet first!')
69
74
  }
70
75
 
71
76
  const detail: WalletDetail = await this.APIService.getWalletDetail(
72
- WalletAddressType.Evm,
77
+ AddressType.Evm,
73
78
  this.walletDetail?.WalletID
74
79
  )
75
80
 
@@ -1,10 +1,11 @@
1
- import { APIService, WalletAddressType, WalletDetail } from './api'
2
- import { APICredentials, TransactionStatusResponse, TxStatus, TransactionError } from './types'
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
@@ -12,12 +13,14 @@ export class SolanaSigner {
12
13
  private APIKey: string
13
14
  private walletDetail: WalletDetail
14
15
  private pollerOptions?: StatusPollerOptions
16
+ private APICredentials!: APICredentials
15
17
 
16
18
  constructor(
17
19
  credentials: APICredentials,
18
20
  environment: Environment,
19
21
  pollerOptions?: StatusPollerOptions
20
22
  ) {
23
+ this.APICredentials = credentials
21
24
  this.APIKey = credentials.apiKey
22
25
  this.APIService = new APIService(credentials, environment)
23
26
  this.pollerOptions = pollerOptions
@@ -45,12 +48,16 @@ export class SolanaSigner {
45
48
  return this.address
46
49
  }
47
50
 
48
- if (!this.APIKey && !this.walletDetail?.WalletID) {
51
+ if (
52
+ !this.APICredentials.apiKey &&
53
+ !this.APICredentials.apiSecret &&
54
+ !this.walletDetail?.WalletID
55
+ ) {
49
56
  throw new Error('Wallet detail not found, use setWallet(walletId) to set wallet first!')
50
57
  }
51
58
 
52
59
  const detail: WalletDetail = await this.APIService.getWalletDetail(
53
- WalletAddressType.Sol,
60
+ AddressType.Solana,
54
61
  this.walletDetail?.WalletID
55
62
  )
56
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,24 +12,13 @@ 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
29
18
  apiSecret: string
19
+
20
+ // Optional
21
+ authToken?: string
30
22
  }
31
23
 
32
24
  export interface WebhookEvent {
@@ -76,20 +68,12 @@ export interface TransactionStatusResponse {
76
68
  failed_reason?: string
77
69
  }
78
70
 
79
- // Wallets
80
- export enum WalletType {
81
- Standard = 'standard',
82
- MPC = 'mpc'
83
- }
84
-
85
71
  export interface CreateWalletOptions {
86
72
  name: string
87
73
  walletType: WalletType
88
- }
89
- export enum WalletCreationStatus {
90
- Pending = 'pending',
91
- Success = 'success',
92
- Error = 'error'
74
+ walletPurpose?: WalletPurpose
75
+ sweepTaskParams?: SweepTaskParams
76
+ sweepTaskId?: string
93
77
  }
94
78
 
95
79
  export interface CreateWalletResponse {
@@ -149,13 +133,13 @@ export interface WalletAsset {
149
133
  asset: WalletAssetDetail
150
134
  }
151
135
 
152
- export enum AddressType {
153
- Evm = 'evm',
154
- Solana = 'sol'
155
- }
156
-
157
136
  export interface DepositAddressResponse {
158
137
  asset_id?: string
159
138
  address: string
160
139
  qr_code: string
161
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)