@upshiftfinance/sdk 0.3.0 → 0.4.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 +1 -1
- package/lib/abis/KycRegistry.d.ts +109 -0
- package/lib/abis/KycRegistry.js +73 -0
- package/lib/abis/index.d.ts +1 -0
- package/lib/abis/index.js +1 -0
- package/lib/adapters/sui/actions.d.ts +174 -0
- package/lib/adapters/sui/actions.js +382 -0
- package/lib/adapters/sui/getters.d.ts +166 -0
- package/lib/adapters/sui/getters.js +391 -0
- package/lib/adapters/sui/index.d.ts +95 -2
- package/lib/adapters/sui/index.js +92 -2
- package/lib/adapters/sui/targets.d.ts +35 -0
- package/lib/adapters/sui/targets.js +35 -0
- package/lib/core/analytics/method-taxonomy.d.ts +1 -1
- package/lib/core/analytics/method-taxonomy.js +7 -0
- package/lib/core/analytics/version.d.ts +1 -1
- package/lib/core/analytics/version.js +1 -1
- package/lib/core/constants/core.d.ts +5 -0
- package/lib/core/constants/core.js +5 -0
- package/lib/core/constants/kyc.d.ts +9 -0
- package/lib/core/constants/kyc.js +12 -0
- package/lib/core/constants/web3.d.ts +2 -2
- package/lib/core/constants/web3.js +9 -2
- package/lib/core/errors/index.d.ts +77 -1
- package/lib/core/errors/index.js +94 -1
- package/lib/core/fetcher.d.ts +5 -0
- package/lib/core/fetcher.js +1 -1
- package/lib/core/helpers/chain-support.d.ts +2 -2
- package/lib/core/helpers/chain-support.js +3 -3
- package/lib/core/helpers/kyc.d.ts +47 -0
- package/lib/core/helpers/kyc.js +111 -0
- package/lib/core/helpers/revert-decode.js +3 -2
- package/lib/core/index.d.ts +2 -0
- package/lib/core/index.js +2 -0
- package/lib/main.d.ts +31 -3
- package/lib/main.js +32 -0
- package/lib/modules/api/kyc.d.ts +4 -0
- package/lib/modules/api/kyc.js +148 -0
- package/lib/modules/api/main.d.ts +63 -1
- package/lib/modules/api/main.js +64 -0
- package/lib/modules/vaults/getters.d.ts +3 -1
- package/lib/modules/vaults/getters.js +53 -9
- package/lib/modules/vaults/main.d.ts +39 -3
- package/lib/modules/vaults/main.js +79 -5
- package/lib/modules/vaults/types.d.ts +7 -1
- package/lib/modules/vaults/utils.js +4 -1
- package/lib/sdk.d.ts +15131 -14393
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +1 -0
- package/lib/types/kyc.d.ts +61 -0
- package/lib/types/kyc.js +3 -0
- package/lib/types/vaults.d.ts +2 -0
- package/lib/types/webserver.d.ts +5 -0
- package/package.json +1 -1
package/lib/core/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from './constants/core';
|
|
|
11
11
|
export * from './constants/web3';
|
|
12
12
|
export * from './constants/vaults';
|
|
13
13
|
export * from './constants/swap-router';
|
|
14
|
+
export * from './constants/kyc';
|
|
14
15
|
export * from './helpers/web3';
|
|
15
16
|
export * from './helpers/multicall';
|
|
16
17
|
export * from './helpers/vaults';
|
|
@@ -20,4 +21,5 @@ export * from './helpers/core';
|
|
|
20
21
|
export * from './helpers/adapters';
|
|
21
22
|
export * from './helpers/signer';
|
|
22
23
|
export * from './helpers/swap-router';
|
|
24
|
+
export * from './helpers/kyc';
|
|
23
25
|
export * from './helpers/revert-decode';
|
package/lib/core/index.js
CHANGED
|
@@ -27,6 +27,7 @@ __exportStar(require("./constants/core"), exports);
|
|
|
27
27
|
__exportStar(require("./constants/web3"), exports);
|
|
28
28
|
__exportStar(require("./constants/vaults"), exports);
|
|
29
29
|
__exportStar(require("./constants/swap-router"), exports);
|
|
30
|
+
__exportStar(require("./constants/kyc"), exports);
|
|
30
31
|
__exportStar(require("./helpers/web3"), exports);
|
|
31
32
|
__exportStar(require("./helpers/multicall"), exports);
|
|
32
33
|
__exportStar(require("./helpers/vaults"), exports);
|
|
@@ -36,5 +37,6 @@ __exportStar(require("./helpers/core"), exports);
|
|
|
36
37
|
__exportStar(require("./helpers/adapters"), exports);
|
|
37
38
|
__exportStar(require("./helpers/signer"), exports);
|
|
38
39
|
__exportStar(require("./helpers/swap-router"), exports);
|
|
40
|
+
__exportStar(require("./helpers/kyc"), exports);
|
|
39
41
|
__exportStar(require("./helpers/revert-decode"), exports);
|
|
40
42
|
//# sourceMappingURL=index.js.map
|
package/lib/main.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import SolanaAdapter from './adapters/solana';
|
|
|
7
7
|
import SuiAdapter from './adapters/sui';
|
|
8
8
|
import StellarAdapter from './adapters/stellar';
|
|
9
9
|
import EVMAdapter from './adapters/evm';
|
|
10
|
-
import type { IAddress, IChainId, IVaultHistoricalParams } from './types';
|
|
10
|
+
import type { IAddress, IChainId, IKycRecord, IKycStatus, IKycWalletOptions, IVaultHistoricalParams } from './types';
|
|
11
11
|
import { UpshiftBase, type IUpshiftBase } from './core';
|
|
12
12
|
import { UpshiftVaults, type IGetVaultsOptions, type IVaultBaseOptions, type IVaultCustomOptions } from './modules/vaults';
|
|
13
13
|
import type { Signer, Wallet } from 'ethers';
|
|
@@ -266,8 +266,8 @@ export declare class UpshiftSDK extends UpshiftBase {
|
|
|
266
266
|
solanaWallet?: string;
|
|
267
267
|
stellarWallet?: string;
|
|
268
268
|
/**
|
|
269
|
-
* Sui wallet address (`0x` + 64 hex chars).
|
|
270
|
-
*
|
|
269
|
+
* Sui wallet address (`0x` + 64 hex chars). Its share balance is read for
|
|
270
|
+
* each Sui vault; Sui positions have no redemptions in v1.
|
|
271
271
|
*/
|
|
272
272
|
suiWallet?: string;
|
|
273
273
|
options?: IVaultBaseOptions;
|
|
@@ -388,6 +388,34 @@ export declare class UpshiftSDK extends UpshiftBase {
|
|
|
388
388
|
chainId: number;
|
|
389
389
|
originCode: `0x${string}`;
|
|
390
390
|
}): Promise<import("./types").IOriginInfo>;
|
|
391
|
+
/**
|
|
392
|
+
* Read a wallet's status in `chainId`'s `KycRegistry`. Delegates to
|
|
393
|
+
* {@link UpshiftVaults.getKycStatus}.
|
|
394
|
+
* @param options - `chainId` and `wallet`.
|
|
395
|
+
* @returns `'none' | 'active' | 'expired' | 'blocked'`.
|
|
396
|
+
* @throws UpshiftValidationError when no provider is configured or no
|
|
397
|
+
* registry is deployed for `chainId`, or `wallet` is malformed.
|
|
398
|
+
* @throws UpshiftSDKError when the read fails.
|
|
399
|
+
* @example
|
|
400
|
+
* ```ts
|
|
401
|
+
* const status = await upshiftSdk.getKycStatus({ chainId: 1, wallet });
|
|
402
|
+
* ```
|
|
403
|
+
*/
|
|
404
|
+
getKycStatus(options: Omit<IKycWalletOptions, 'rpcUrl'>): Promise<IKycStatus>;
|
|
405
|
+
/**
|
|
406
|
+
* Read a wallet's raw `KycRegistry` record (blocked flag and Unix-second
|
|
407
|
+
* timestamps). Delegates to {@link UpshiftVaults.getKycRecord}.
|
|
408
|
+
* @param options - `chainId` and `wallet`.
|
|
409
|
+
* @returns {@link IKycRecord}.
|
|
410
|
+
* @throws UpshiftValidationError when no provider is configured or no
|
|
411
|
+
* registry is deployed for `chainId`, or `wallet` is malformed.
|
|
412
|
+
* @throws UpshiftSDKError when the read fails.
|
|
413
|
+
* @example
|
|
414
|
+
* ```ts
|
|
415
|
+
* const { expiresAt } = await upshiftSdk.getKycRecord({ chainId: 1, wallet });
|
|
416
|
+
* ```
|
|
417
|
+
*/
|
|
418
|
+
getKycRecord(options: Omit<IKycWalletOptions, 'rpcUrl'>): Promise<IKycRecord>;
|
|
391
419
|
/**
|
|
392
420
|
* Get lifetime PnL for a user in a specific vault.
|
|
393
421
|
* Calculates realized and unrealized PnL based on deposit/withdrawal history and current position.
|
package/lib/main.js
CHANGED
|
@@ -463,6 +463,38 @@ class UpshiftSDK extends core_1.UpshiftBase {
|
|
|
463
463
|
async getOriginInfo(options) {
|
|
464
464
|
return await this.vaults.getOriginInfo(options);
|
|
465
465
|
}
|
|
466
|
+
/**
|
|
467
|
+
* Read a wallet's status in `chainId`'s `KycRegistry`. Delegates to
|
|
468
|
+
* {@link UpshiftVaults.getKycStatus}.
|
|
469
|
+
* @param options - `chainId` and `wallet`.
|
|
470
|
+
* @returns `'none' | 'active' | 'expired' | 'blocked'`.
|
|
471
|
+
* @throws UpshiftValidationError when no provider is configured or no
|
|
472
|
+
* registry is deployed for `chainId`, or `wallet` is malformed.
|
|
473
|
+
* @throws UpshiftSDKError when the read fails.
|
|
474
|
+
* @example
|
|
475
|
+
* ```ts
|
|
476
|
+
* const status = await upshiftSdk.getKycStatus({ chainId: 1, wallet });
|
|
477
|
+
* ```
|
|
478
|
+
*/
|
|
479
|
+
async getKycStatus(options) {
|
|
480
|
+
return await this.vaults.getKycStatus(options);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Read a wallet's raw `KycRegistry` record (blocked flag and Unix-second
|
|
484
|
+
* timestamps). Delegates to {@link UpshiftVaults.getKycRecord}.
|
|
485
|
+
* @param options - `chainId` and `wallet`.
|
|
486
|
+
* @returns {@link IKycRecord}.
|
|
487
|
+
* @throws UpshiftValidationError when no provider is configured or no
|
|
488
|
+
* registry is deployed for `chainId`, or `wallet` is malformed.
|
|
489
|
+
* @throws UpshiftSDKError when the read fails.
|
|
490
|
+
* @example
|
|
491
|
+
* ```ts
|
|
492
|
+
* const { expiresAt } = await upshiftSdk.getKycRecord({ chainId: 1, wallet });
|
|
493
|
+
* ```
|
|
494
|
+
*/
|
|
495
|
+
async getKycRecord(options) {
|
|
496
|
+
return await this.vaults.getKycRecord(options);
|
|
497
|
+
}
|
|
466
498
|
/**
|
|
467
499
|
* Get lifetime PnL for a user in a specific vault.
|
|
468
500
|
* Calculates realized and unrealized PnL based on deposit/withdrawal history and current position.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { IAddress, ICreateKycSessionOptions, IKycChallenge, IKycSession } from '../../types';
|
|
2
|
+
export declare function fetchKycChallenge(wallet: IAddress, chainId: number): Promise<IKycChallenge>;
|
|
3
|
+
export declare function postKycSession(options: ICreateKycSessionOptions): Promise<IKycSession>;
|
|
4
|
+
export declare function postKycSessionRefresh(sessionToken: string): Promise<string>;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fetchKycChallenge = fetchKycChallenge;
|
|
4
|
+
exports.postKycSession = postKycSession;
|
|
5
|
+
exports.postKycSessionRefresh = postKycSessionRefresh;
|
|
6
|
+
const ethers_1 = require("ethers");
|
|
7
|
+
const core_1 = require("../../core/constants/core");
|
|
8
|
+
const errors_1 = require("../../core/errors");
|
|
9
|
+
const fetcher_1 = require("../../core/fetcher");
|
|
10
|
+
const REASONS = {
|
|
11
|
+
'challenge expired': 'challenge_expired',
|
|
12
|
+
'unknown or used challenge': 'challenge_used',
|
|
13
|
+
'invalid signature': 'invalid_signature',
|
|
14
|
+
'unknown or expired session': 'session_expired',
|
|
15
|
+
'session no longer valid': 'session_expired',
|
|
16
|
+
'identity blocked': 'identity_blocked',
|
|
17
|
+
'wallet is bound to another identity': 'wallet_bound',
|
|
18
|
+
'wallet limit reached for this identity': 'wallet_limit',
|
|
19
|
+
'wallet control was proven on another chain; verify again from there': 'other_chain',
|
|
20
|
+
'wallet is verified through another provider': 'other_provider',
|
|
21
|
+
'wallet is not verified for this chain': 'not_verified_for_chain',
|
|
22
|
+
'enrolment already in progress; retry shortly': 'enrolment_in_progress',
|
|
23
|
+
'a registry write for this wallet is in progress; retry shortly': 'registry_write_in_progress',
|
|
24
|
+
'enrolment timed out; retry shortly': 'enrolment_timed_out',
|
|
25
|
+
'chain has no kyc registry': 'no_registry',
|
|
26
|
+
'too many requests': 'rate_limited',
|
|
27
|
+
};
|
|
28
|
+
const IDENTITY_STATUSES = [
|
|
29
|
+
'pending',
|
|
30
|
+
'approved',
|
|
31
|
+
'rejected_retry',
|
|
32
|
+
'rejected_final',
|
|
33
|
+
'revoked',
|
|
34
|
+
'blocked',
|
|
35
|
+
];
|
|
36
|
+
function readDetail(body) {
|
|
37
|
+
const detail = body?.detail;
|
|
38
|
+
if (typeof detail === 'string')
|
|
39
|
+
return detail;
|
|
40
|
+
if (!Array.isArray(detail))
|
|
41
|
+
return '';
|
|
42
|
+
return detail
|
|
43
|
+
.map((d) => d?.msg)
|
|
44
|
+
.filter((m) => typeof m === 'string')
|
|
45
|
+
.join('; ');
|
|
46
|
+
}
|
|
47
|
+
function reasonFor(status, detail) {
|
|
48
|
+
const known = REASONS[detail.toLowerCase()];
|
|
49
|
+
if (known)
|
|
50
|
+
return known;
|
|
51
|
+
if (/has no KYC registry/i.test(detail))
|
|
52
|
+
return 'no_registry';
|
|
53
|
+
if (status === 429)
|
|
54
|
+
return 'rate_limited';
|
|
55
|
+
if (status >= 500)
|
|
56
|
+
return 'unavailable';
|
|
57
|
+
if (status === 422)
|
|
58
|
+
return 'invalid_request';
|
|
59
|
+
return 'unknown';
|
|
60
|
+
}
|
|
61
|
+
async function kycRequest(method, path, data) {
|
|
62
|
+
const res = await (0, fetcher_1.fetchUpshiftPublic)(path, {
|
|
63
|
+
method: data === undefined ? 'get' : 'post',
|
|
64
|
+
data,
|
|
65
|
+
returnErrorResponse: true,
|
|
66
|
+
});
|
|
67
|
+
const body = await res.json().catch(() => null);
|
|
68
|
+
if (res.ok) {
|
|
69
|
+
if (body && typeof body === 'object')
|
|
70
|
+
return body;
|
|
71
|
+
throw new errors_1.UpshiftServerError(res.status, `${method}: empty response body`);
|
|
72
|
+
}
|
|
73
|
+
const detail = readDetail(body);
|
|
74
|
+
const retryAfter = Number(res.headers.get('retry-after'));
|
|
75
|
+
throw new errors_1.UpshiftKycError(res.status, detail, reasonFor(res.status, detail), {
|
|
76
|
+
correlationId: res.headers.get('x-correlation-id') ?? undefined,
|
|
77
|
+
context: { method, status: res.status },
|
|
78
|
+
retryAfterMs: retryAfter > 0 ? retryAfter * 1000 : undefined,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function assertWalletAndChain(method, wallet, chainId) {
|
|
82
|
+
if (!(0, ethers_1.isAddress)(wallet)) {
|
|
83
|
+
throw new errors_1.UpshiftValidationError('INVALID_ADDRESS', `${method}: wallet is not a valid EVM address`);
|
|
84
|
+
}
|
|
85
|
+
if (!Number.isInteger(chainId) || chainId < 1) {
|
|
86
|
+
throw new errors_1.UpshiftValidationError('INVALID_CHAIN', `${method}: chainId must be a positive integer, got ${chainId}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function field(method, body, key, check) {
|
|
90
|
+
const value = body[key];
|
|
91
|
+
if (!check(value)) {
|
|
92
|
+
throw new errors_1.UpshiftServerError(200, `${method}: response field ${key} is malformed`);
|
|
93
|
+
}
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
const isString = (v) => typeof v === 'string' && v.length > 0;
|
|
97
|
+
const isInteger = (v) => Number.isInteger(v);
|
|
98
|
+
const isIdentityStatus = (v) => IDENTITY_STATUSES.includes(v);
|
|
99
|
+
async function fetchKycChallenge(wallet, chainId) {
|
|
100
|
+
const method = 'getKycChallenge';
|
|
101
|
+
assertWalletAndChain(method, wallet, chainId);
|
|
102
|
+
const body = await kycRequest(method, core_1.WEBSERVER_ENDPOINTS.public.kyc.challenge(wallet, chainId));
|
|
103
|
+
return {
|
|
104
|
+
wallet: field(method, body, 'wallet', isString),
|
|
105
|
+
chainId: field(method, body, 'chain_id', isInteger),
|
|
106
|
+
nonce: field(method, body, 'nonce', isString),
|
|
107
|
+
issuedAt: field(method, body, 'issued_at', isInteger),
|
|
108
|
+
expiry: field(method, body, 'expiry', isInteger),
|
|
109
|
+
message: field(method, body, 'message', isString),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async function postKycSession(options) {
|
|
113
|
+
const method = 'createKycSession';
|
|
114
|
+
const { wallet, chainId, nonce, issuedAt, expiry, signature } = options;
|
|
115
|
+
assertWalletAndChain(method, wallet, chainId);
|
|
116
|
+
if (!/^0x[0-9a-fA-F]+$/.test(signature)) {
|
|
117
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${method}: signature must be 0x-prefixed hex`);
|
|
118
|
+
}
|
|
119
|
+
if (!isString(nonce) || !isInteger(issuedAt) || !isInteger(expiry)) {
|
|
120
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${method}: nonce, issuedAt and expiry must come from getKycChallenge`);
|
|
121
|
+
}
|
|
122
|
+
const body = await kycRequest(method, core_1.WEBSERVER_ENDPOINTS.public.kyc.session, {
|
|
123
|
+
wallet,
|
|
124
|
+
chain_id: chainId,
|
|
125
|
+
nonce,
|
|
126
|
+
issued_at: issuedAt,
|
|
127
|
+
expiry,
|
|
128
|
+
signature,
|
|
129
|
+
});
|
|
130
|
+
return {
|
|
131
|
+
accessToken: field(method, body, 'access_token', isString),
|
|
132
|
+
sessionToken: field(method, body, 'session_token', isString),
|
|
133
|
+
externalUserId: field(method, body, 'external_user_id', isString),
|
|
134
|
+
levelName: field(method, body, 'level_name', isString),
|
|
135
|
+
identityStatus: field(method, body, 'identity_status', isIdentityStatus),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
async function postKycSessionRefresh(sessionToken) {
|
|
139
|
+
const method = 'refreshKycSession';
|
|
140
|
+
if (typeof sessionToken !== 'string' ||
|
|
141
|
+
sessionToken.length < 16 ||
|
|
142
|
+
sessionToken.length > 128) {
|
|
143
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', `${method}: sessionToken must come from createKycSession`);
|
|
144
|
+
}
|
|
145
|
+
const body = await kycRequest(method, core_1.WEBSERVER_ENDPOINTS.public.kyc.sessionRefresh, { session_token: sessionToken });
|
|
146
|
+
return field(method, body, 'access_token', isString);
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=kyc.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { UpshiftBase, type IUpshiftBase } from '../../core/base.class';
|
|
2
|
-
import type { ICollateralExcessOrDeficit, ICollateralSimulationInput, ICollateralSimulationResults, ICuratorWhitelistStatus, IDiscountFactorLadder, ILoanBookInfo, IOracleClassification, IOtcMarginRequirement, IOtcPositionRead, IRevertReason, ITimelockRequest, ITransparencyApySeries, ITransparencyAuditCategory, ITransparencyAuditLog, ITransparencyFees, ITransparencyGovernancePermissions, ITransparencyGovernanceRoles, ITransparencyHistoricalAllocations, ITransparencyPositions, ITransparencyRatioPoint, ITransparencyTimelocks, ITransparencyTimelockStatus, IUnrealizedPnlSnapshot, IVaultPerformanceFees, IWSSubaccountListItem } from '../../types';
|
|
2
|
+
import type { IAddress, ICollateralExcessOrDeficit, ICollateralSimulationInput, ICollateralSimulationResults, ICreateKycSessionOptions, ICuratorWhitelistStatus, IDiscountFactorLadder, IKycChallenge, IKycSession, ILoanBookInfo, IOracleClassification, IOtcMarginRequirement, IOtcPositionRead, IRevertReason, ITimelockRequest, ITransparencyApySeries, ITransparencyAuditCategory, ITransparencyAuditLog, ITransparencyFees, ITransparencyGovernancePermissions, ITransparencyGovernanceRoles, ITransparencyHistoricalAllocations, ITransparencyPositions, ITransparencyRatioPoint, ITransparencyTimelocks, ITransparencyTimelockStatus, IUnrealizedPnlSnapshot, IVaultPerformanceFees, IWSSubaccountListItem } from '../../types';
|
|
3
3
|
/**
|
|
4
4
|
* Read-only client for Upshift backend REST endpoints that have no on-chain
|
|
5
5
|
* equivalent: the unrealized-PnL series, the transparency dashboard
|
|
@@ -584,4 +584,66 @@ export declare class UpshiftApi extends UpshiftBase {
|
|
|
584
584
|
* const losing = all.filter((s) => s.unrealizedPnl < 0);
|
|
585
585
|
*/
|
|
586
586
|
getLatestUnrealizedPnl(): Promise<IUnrealizedPnlSnapshot[]>;
|
|
587
|
+
/**
|
|
588
|
+
* Fetch a one-time SIWE challenge that proves the wallet is the user's
|
|
589
|
+
* before KYC starts (`GET /kyc/challenge`).
|
|
590
|
+
*
|
|
591
|
+
* Makes one HTTPS request to the public Upshift API; no RPC calls. Never
|
|
592
|
+
* cached: the nonce is single use and expires after 600 s.
|
|
593
|
+
*
|
|
594
|
+
* @param params - `wallet`, the EVM wallet that will sign `message`, and
|
|
595
|
+
* `chainId`, the EVM chain whose `KycRegistry` the session activates.
|
|
596
|
+
* @returns {@link IKycChallenge}. Sign `message` verbatim with `personal_sign`.
|
|
597
|
+
* @throws UpshiftValidationError When `wallet` or `chainId` is malformed.
|
|
598
|
+
* @throws UpshiftKycError When the backend answers non-2xx: `no_registry` (400) or `unavailable` (503).
|
|
599
|
+
* @throws UpshiftServerError When the response body is malformed.
|
|
600
|
+
* @example
|
|
601
|
+
* ```ts
|
|
602
|
+
* const challenge = await sdk.apiModule.getKycChallenge({ wallet, chainId: 1 });
|
|
603
|
+
* const signature = await walletClient.signMessage({ message: challenge.message });
|
|
604
|
+
* ```
|
|
605
|
+
*/
|
|
606
|
+
getKycChallenge(params: {
|
|
607
|
+
wallet: IAddress;
|
|
608
|
+
chainId: number;
|
|
609
|
+
}): Promise<IKycChallenge>;
|
|
610
|
+
/**
|
|
611
|
+
* Open a KYC session with a signed challenge (`POST /kyc/session`). The
|
|
612
|
+
* first call creates the user's Sumsub applicant; later calls resume it.
|
|
613
|
+
* Every call activates the identity on `chainId`.
|
|
614
|
+
*
|
|
615
|
+
* Makes one HTTPS request and never retries: the nonce is single use. On
|
|
616
|
+
* any failure, fetch a new challenge before trying again.
|
|
617
|
+
*
|
|
618
|
+
* @param options - The challenge fields exactly as returned, plus `signature`.
|
|
619
|
+
* @returns {@link IKycSession} with the Sumsub WebSDK `accessToken`.
|
|
620
|
+
* @throws UpshiftValidationError When an input is malformed.
|
|
621
|
+
* @throws UpshiftKycError When the backend answers non-2xx. `reason` names the
|
|
622
|
+
* case; `retryable` is true for the in-progress and timed-out answers.
|
|
623
|
+
* @throws UpshiftServerError When the response body is malformed.
|
|
624
|
+
* @example
|
|
625
|
+
* ```ts
|
|
626
|
+
* const session = await sdk.apiModule.createKycSession({ ...challenge, signature });
|
|
627
|
+
* openSumsubWidget(session.accessToken);
|
|
628
|
+
* ```
|
|
629
|
+
*/
|
|
630
|
+
createKycSession(options: ICreateKycSessionOptions): Promise<IKycSession>;
|
|
631
|
+
/**
|
|
632
|
+
* Get a fresh Sumsub WebSDK access token for an open session without a new
|
|
633
|
+
* signature (`POST /kyc/session/refresh`). A session lasts 4 h.
|
|
634
|
+
*
|
|
635
|
+
* Makes one HTTPS request; no RPC calls.
|
|
636
|
+
*
|
|
637
|
+
* @param params - `sessionToken` from {@link UpshiftApi.createKycSession}.
|
|
638
|
+
* @returns The new Sumsub access token.
|
|
639
|
+
* @throws UpshiftValidationError When `sessionToken` is malformed.
|
|
640
|
+
* @throws UpshiftKycError When the backend answers non-2xx: `session_expired` (401) once the session ends or the wallet is unbound.
|
|
641
|
+
* @example
|
|
642
|
+
* ```ts
|
|
643
|
+
* const expirationHandler = () => sdk.apiModule.refreshKycSession({ sessionToken });
|
|
644
|
+
* ```
|
|
645
|
+
*/
|
|
646
|
+
refreshKycSession(params: {
|
|
647
|
+
sessionToken: string;
|
|
648
|
+
}): Promise<string>;
|
|
587
649
|
}
|
package/lib/modules/api/main.js
CHANGED
|
@@ -10,6 +10,7 @@ exports.UpshiftApi = void 0;
|
|
|
10
10
|
*/
|
|
11
11
|
const ethers_1 = require("ethers");
|
|
12
12
|
const fetcher_1 = require("./fetcher");
|
|
13
|
+
const kyc_1 = require("./kyc");
|
|
13
14
|
const base_class_1 = require("../../core/base.class");
|
|
14
15
|
const core_1 = require("../../core/constants/core");
|
|
15
16
|
const errors_1 = require("../../core/errors");
|
|
@@ -906,6 +907,69 @@ class UpshiftApi extends base_class_1.UpshiftBase {
|
|
|
906
907
|
assertSnapshotArray(data, method);
|
|
907
908
|
return data.map(toUnrealizedPnlSnapshot);
|
|
908
909
|
}
|
|
910
|
+
/**
|
|
911
|
+
* Fetch a one-time SIWE challenge that proves the wallet is the user's
|
|
912
|
+
* before KYC starts (`GET /kyc/challenge`).
|
|
913
|
+
*
|
|
914
|
+
* Makes one HTTPS request to the public Upshift API; no RPC calls. Never
|
|
915
|
+
* cached: the nonce is single use and expires after 600 s.
|
|
916
|
+
*
|
|
917
|
+
* @param params - `wallet`, the EVM wallet that will sign `message`, and
|
|
918
|
+
* `chainId`, the EVM chain whose `KycRegistry` the session activates.
|
|
919
|
+
* @returns {@link IKycChallenge}. Sign `message` verbatim with `personal_sign`.
|
|
920
|
+
* @throws UpshiftValidationError When `wallet` or `chainId` is malformed.
|
|
921
|
+
* @throws UpshiftKycError When the backend answers non-2xx: `no_registry` (400) or `unavailable` (503).
|
|
922
|
+
* @throws UpshiftServerError When the response body is malformed.
|
|
923
|
+
* @example
|
|
924
|
+
* ```ts
|
|
925
|
+
* const challenge = await sdk.apiModule.getKycChallenge({ wallet, chainId: 1 });
|
|
926
|
+
* const signature = await walletClient.signMessage({ message: challenge.message });
|
|
927
|
+
* ```
|
|
928
|
+
*/
|
|
929
|
+
async getKycChallenge(params) {
|
|
930
|
+
return (0, kyc_1.fetchKycChallenge)(params.wallet, params.chainId);
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Open a KYC session with a signed challenge (`POST /kyc/session`). The
|
|
934
|
+
* first call creates the user's Sumsub applicant; later calls resume it.
|
|
935
|
+
* Every call activates the identity on `chainId`.
|
|
936
|
+
*
|
|
937
|
+
* Makes one HTTPS request and never retries: the nonce is single use. On
|
|
938
|
+
* any failure, fetch a new challenge before trying again.
|
|
939
|
+
*
|
|
940
|
+
* @param options - The challenge fields exactly as returned, plus `signature`.
|
|
941
|
+
* @returns {@link IKycSession} with the Sumsub WebSDK `accessToken`.
|
|
942
|
+
* @throws UpshiftValidationError When an input is malformed.
|
|
943
|
+
* @throws UpshiftKycError When the backend answers non-2xx. `reason` names the
|
|
944
|
+
* case; `retryable` is true for the in-progress and timed-out answers.
|
|
945
|
+
* @throws UpshiftServerError When the response body is malformed.
|
|
946
|
+
* @example
|
|
947
|
+
* ```ts
|
|
948
|
+
* const session = await sdk.apiModule.createKycSession({ ...challenge, signature });
|
|
949
|
+
* openSumsubWidget(session.accessToken);
|
|
950
|
+
* ```
|
|
951
|
+
*/
|
|
952
|
+
async createKycSession(options) {
|
|
953
|
+
return (0, kyc_1.postKycSession)(options);
|
|
954
|
+
}
|
|
955
|
+
/**
|
|
956
|
+
* Get a fresh Sumsub WebSDK access token for an open session without a new
|
|
957
|
+
* signature (`POST /kyc/session/refresh`). A session lasts 4 h.
|
|
958
|
+
*
|
|
959
|
+
* Makes one HTTPS request; no RPC calls.
|
|
960
|
+
*
|
|
961
|
+
* @param params - `sessionToken` from {@link UpshiftApi.createKycSession}.
|
|
962
|
+
* @returns The new Sumsub access token.
|
|
963
|
+
* @throws UpshiftValidationError When `sessionToken` is malformed.
|
|
964
|
+
* @throws UpshiftKycError When the backend answers non-2xx: `session_expired` (401) once the session ends or the wallet is unbound.
|
|
965
|
+
* @example
|
|
966
|
+
* ```ts
|
|
967
|
+
* const expirationHandler = () => sdk.apiModule.refreshKycSession({ sessionToken });
|
|
968
|
+
* ```
|
|
969
|
+
*/
|
|
970
|
+
async refreshKycSession(params) {
|
|
971
|
+
return (0, kyc_1.postKycSessionRefresh)(params.sessionToken);
|
|
972
|
+
}
|
|
909
973
|
}
|
|
910
974
|
exports.UpshiftApi = UpshiftApi;
|
|
911
975
|
//# sourceMappingURL=main.js.map
|
|
@@ -119,11 +119,13 @@ export { getSwapRouterDepositResult } from '../../core/helpers/swap-router';
|
|
|
119
119
|
/**
|
|
120
120
|
* Vault Positions
|
|
121
121
|
*/
|
|
122
|
-
export declare function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, options, prefetchedReads, }: {
|
|
122
|
+
export declare function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, suiWallet, options, prefetchedReads, }: {
|
|
123
123
|
vault: IAddress;
|
|
124
124
|
wallet?: IAddress;
|
|
125
125
|
solanaWallet?: string;
|
|
126
126
|
stellarWallet?: string;
|
|
127
|
+
/** Sui wallet whose share balance is read for Sui vaults. */
|
|
128
|
+
suiWallet?: string;
|
|
127
129
|
options: IVaultBaseOptions;
|
|
128
130
|
/**
|
|
129
131
|
* Per-vault values already read via a Multicall3 batch at the fan-out call
|
|
@@ -88,6 +88,8 @@ const SolanaConstants = __importStar(require("../../adapters/solana/constants"))
|
|
|
88
88
|
const withdrawal_queue_1 = require("../../adapters/solana/withdrawal-queue");
|
|
89
89
|
const web3_js_1 = require("@solana/web3.js");
|
|
90
90
|
const StellarGetters = __importStar(require("../../adapters/stellar/getters"));
|
|
91
|
+
const SuiGetters = __importStar(require("../../adapters/sui/getters"));
|
|
92
|
+
const chain_address_1 = require("../../core/helpers/chain-address");
|
|
91
93
|
const utils_3 = require("../../adapters/stellar/utils");
|
|
92
94
|
const constants_1 = require("../../adapters/stellar/constants");
|
|
93
95
|
const EVM = __importStar(require("../../adapters/evm"));
|
|
@@ -160,6 +162,10 @@ async function getVault({ vault, loans = false, allocations = false, options, lo
|
|
|
160
162
|
returnedVault = await StellarGetters.getStellarVault(tokenizedVault, options);
|
|
161
163
|
break;
|
|
162
164
|
}
|
|
165
|
+
case 'sui-0': {
|
|
166
|
+
returnedVault = await SuiGetters.getSuiVault(tokenizedVault, options);
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
163
169
|
case 'evm-2': {
|
|
164
170
|
returnedVault = await EVM.getEvmVaultV2(tokenizedVault, options);
|
|
165
171
|
break;
|
|
@@ -968,9 +974,9 @@ async function readSolanaRedemptions(input) {
|
|
|
968
974
|
}
|
|
969
975
|
async function getVaultAvailableRedemptions({ vault, wallet, options, prefetchedReads, }) {
|
|
970
976
|
try {
|
|
971
|
-
// Stellar vaults don't support on-chain redemptions yet
|
|
972
|
-
if ((0, utils_3.isStellarAddress)(vault)) {
|
|
973
|
-
core_1.Logger.log.warn('getVaultAvailableRedemptions', `Available redemptions is not yet supported for
|
|
977
|
+
// Stellar and Sui vaults don't support on-chain redemptions yet
|
|
978
|
+
if ((0, utils_3.isStellarAddress)(vault) || (0, chain_address_1.isSuiAddress)(vault)) {
|
|
979
|
+
core_1.Logger.log.warn('getVaultAvailableRedemptions', `Available redemptions is not yet supported for this vault: ${vault}`);
|
|
974
980
|
return {
|
|
975
981
|
availableRedemptions: [],
|
|
976
982
|
pendingRedemptions: [],
|
|
@@ -1305,9 +1311,9 @@ async function getVaultAvailableRedemptions({ vault, wallet, options, prefetched
|
|
|
1305
1311
|
}
|
|
1306
1312
|
async function getVaultRedemptionHistory({ vault, wallet, lookbackBlocks, options, }) {
|
|
1307
1313
|
try {
|
|
1308
|
-
// Stellar vaults: no on-chain redemption history yet
|
|
1309
|
-
if ((0, utils_3.isStellarAddress)(vault)) {
|
|
1310
|
-
core_1.Logger.log.warn('getVaultRedemptionHistory', `Redemption history is not yet supported for
|
|
1314
|
+
// Stellar and Sui vaults: no on-chain redemption history yet
|
|
1315
|
+
if ((0, utils_3.isStellarAddress)(vault) || (0, chain_address_1.isSuiAddress)(vault)) {
|
|
1316
|
+
core_1.Logger.log.warn('getVaultRedemptionHistory', `Redemption history is not yet supported for this vault: ${vault}`);
|
|
1311
1317
|
return [];
|
|
1312
1318
|
}
|
|
1313
1319
|
// setup
|
|
@@ -1481,7 +1487,7 @@ Object.defineProperty(exports, "getSwapRouterDepositResult", { enumerable: true,
|
|
|
1481
1487
|
/**
|
|
1482
1488
|
* Vault Positions
|
|
1483
1489
|
*/
|
|
1484
|
-
async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, options, prefetchedReads, }) {
|
|
1490
|
+
async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, suiWallet, options, prefetchedReads, }) {
|
|
1485
1491
|
try {
|
|
1486
1492
|
const tokenizedVaults = await (0, core_1.fetchTokenizedVault)(vault ? vault : undefined, options?.headers, false, false);
|
|
1487
1493
|
if (!tokenizedVaults || tokenizedVaults.length === 0) {
|
|
@@ -1594,6 +1600,32 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
|
|
|
1594
1600
|
walletBalance: balance,
|
|
1595
1601
|
};
|
|
1596
1602
|
}
|
|
1603
|
+
if ((0, chain_address_1.isSuiAddress)(v.address)) {
|
|
1604
|
+
// The contract gives shares the deposit coin's decimals.
|
|
1605
|
+
const decimals = v.sui_vault_metadata?.deposit_token_decimals;
|
|
1606
|
+
const shareCoinType = v.sui_vault_metadata?.share_coin_type;
|
|
1607
|
+
const network = v.sui_vault_metadata?.network_name;
|
|
1608
|
+
let balance = (0, core_1.toNormalizedBn)(0, decimals ?? 0);
|
|
1609
|
+
// No metadata at all: a legacy Ember/Gamma vault, nothing to read.
|
|
1610
|
+
if (suiWallet && (0, chain_address_1.isSuiAddress)(suiWallet) && v.sui_vault_metadata) {
|
|
1611
|
+
if (decimals == null || !shareCoinType || !network) {
|
|
1612
|
+
// Without the share type or its decimals there is nothing to
|
|
1613
|
+
// read or no way to scale it: fail the row, don't show zero.
|
|
1614
|
+
throw new errors_1.UpshiftValidationError('INVALID_INPUT', 'getVaultPositions: Sui vault is missing sui_vault_metadata share type, decimals or network', { context: { vault: v.address } });
|
|
1615
|
+
}
|
|
1616
|
+
const shares = await SuiGetters.getSuiShareBalance(suiWallet, shareCoinType, network, options.sui);
|
|
1617
|
+
balance = (0, core_1.toNormalizedBn)(shares, decimals);
|
|
1618
|
+
}
|
|
1619
|
+
// Sui vaults have no redemption reads in v1.
|
|
1620
|
+
return {
|
|
1621
|
+
vault: v.address,
|
|
1622
|
+
status: renderStatus([], balance),
|
|
1623
|
+
availableRedemptions: [],
|
|
1624
|
+
pendingRedemptions: [],
|
|
1625
|
+
redeemable: (0, core_1.toNormalizedBn)(0),
|
|
1626
|
+
walletBalance: balance,
|
|
1627
|
+
};
|
|
1628
|
+
}
|
|
1597
1629
|
// create provider
|
|
1598
1630
|
const provider = (0, core_1.createProvider)(options.rpcUrl);
|
|
1599
1631
|
// version split logic
|
|
@@ -1709,6 +1741,7 @@ async function getVaultPositions({ vault, wallet, solanaWallet, stellarWallet, o
|
|
|
1709
1741
|
wallet,
|
|
1710
1742
|
solanaWallet,
|
|
1711
1743
|
stellarWallet,
|
|
1744
|
+
suiWallet,
|
|
1712
1745
|
});
|
|
1713
1746
|
throw new Error(`#getVaultPositions::${vault}:${e?.message}`);
|
|
1714
1747
|
}
|
|
@@ -1897,6 +1930,14 @@ async function getVaultTvl({ vault, options, historical, }) {
|
|
|
1897
1930
|
},
|
|
1898
1931
|
];
|
|
1899
1932
|
}
|
|
1933
|
+
if (version === 'sui-0') {
|
|
1934
|
+
return [
|
|
1935
|
+
{
|
|
1936
|
+
value: (0, utils_1.backendTvlToNormalizedBn)(_vaultExists?.latest_reported_tvl, _vaultExists?.sui_vault_metadata?.deposit_token_decimals ?? 0),
|
|
1937
|
+
timestamp: new Date().toISOString(),
|
|
1938
|
+
},
|
|
1939
|
+
];
|
|
1940
|
+
}
|
|
1900
1941
|
if (version === 'stellar-0') {
|
|
1901
1942
|
const stellarDecimals = _vaultExists?.stellar_vault_metadata?.deposit_token_decimals ??
|
|
1902
1943
|
constants_1.STELLAR_FALLBACK_DECIMALS;
|
|
@@ -1957,7 +1998,9 @@ async function getVaultTvl({ vault, options, historical, }) {
|
|
|
1957
1998
|
// historical tvl
|
|
1958
1999
|
// check vault version early to guard non-EVM chains
|
|
1959
2000
|
const version = (0, core_1.getVaultVersionV2)(_vaultExists);
|
|
1960
|
-
if (version === 'stellar-0' ||
|
|
2001
|
+
if (version === 'stellar-0' ||
|
|
2002
|
+
version === 'sol-0' ||
|
|
2003
|
+
version === 'sui-0') {
|
|
1961
2004
|
core_1.Logger.log.warn('getVaultTvl:historical', 'Historical TVL not supported for non-EVM vaults', { vault, version });
|
|
1962
2005
|
return [];
|
|
1963
2006
|
}
|
|
@@ -2349,7 +2392,8 @@ async function getYieldLastRealizedOn({ vault, options, }) {
|
|
|
2349
2392
|
break;
|
|
2350
2393
|
}
|
|
2351
2394
|
case 'sol-0':
|
|
2352
|
-
case 'stellar-0':
|
|
2395
|
+
case 'stellar-0':
|
|
2396
|
+
case 'sui-0': {
|
|
2353
2397
|
return 0;
|
|
2354
2398
|
}
|
|
2355
2399
|
default: {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Export getters
|
|
8
8
|
*/
|
|
9
9
|
export * from './getters';
|
|
10
|
-
import type { IAddress, IChainId, IGetOriginInfoOptions, INormalizedNumber, IOriginInfo, IVaultHistoricalParams, IVaultPosition, IVaultUserHistoryItem } from '../../types';
|
|
10
|
+
import type { IAddress, IChainId, IGetOriginInfoOptions, IKycRecord, IKycStatus, IKycWalletOptions, INormalizedNumber, IOriginInfo, IVaultHistoricalParams, IVaultPosition, IVaultUserHistoryItem } from '../../types';
|
|
11
11
|
import type SolanaAdapter from '../../adapters/solana';
|
|
12
12
|
import { UpshiftBase, type IUpshiftBase } from '../../core';
|
|
13
13
|
import { type IContractWriteOptions, type INativeDepositOptions } from './write.actions';
|
|
@@ -27,6 +27,8 @@ export declare class UpshiftVaults extends UpshiftBase {
|
|
|
27
27
|
* vaults (see `IVaultBaseOptions.stellarRpc`).
|
|
28
28
|
*/
|
|
29
29
|
private _stellarRpc?;
|
|
30
|
+
/** The SDK's `sui` config, for Sui vault reads (see `IVaultBaseOptions.sui`). */
|
|
31
|
+
private _sui?;
|
|
30
32
|
constructor(baseConfig: IUpshiftBase, solana: SolanaAdapter);
|
|
31
33
|
/**
|
|
32
34
|
* @description deposit underlying token into the specified pool with adapter support. This is for when we cannot pass in a signer in sdk and need to do so as an arg
|
|
@@ -240,8 +242,8 @@ export declare class UpshiftVaults extends UpshiftBase {
|
|
|
240
242
|
solanaWallet?: string;
|
|
241
243
|
stellarWallet?: string;
|
|
242
244
|
/**
|
|
243
|
-
* Sui wallet address (`0x` + 64 hex chars).
|
|
244
|
-
*
|
|
245
|
+
* Sui wallet address (`0x` + 64 hex chars). Its share balance is read for
|
|
246
|
+
* each Sui vault; Sui positions have no redemptions in v1.
|
|
245
247
|
*/
|
|
246
248
|
suiWallet?: string;
|
|
247
249
|
options?: IVaultBaseOptions;
|
|
@@ -408,6 +410,40 @@ export declare class UpshiftVaults extends UpshiftBase {
|
|
|
408
410
|
* ```
|
|
409
411
|
*/
|
|
410
412
|
getOriginInfo(options: Omit<IGetOriginInfoOptions, 'rpcUrl'>): Promise<IOriginInfo>;
|
|
413
|
+
/**
|
|
414
|
+
* Read a wallet's KYC status through this instance's provider for
|
|
415
|
+
* `chainId`. See {@link getKycStatus}.
|
|
416
|
+
*
|
|
417
|
+
* @param options - `chainId` and `wallet`.
|
|
418
|
+
* @returns The wallet's {@link IKycStatus}.
|
|
419
|
+
* @throws UpshiftValidationError (`INVALID_CHAIN`) when no provider is
|
|
420
|
+
* configured or no registry is deployed for `chainId`;
|
|
421
|
+
* (`INVALID_ADDRESS`) for a malformed wallet.
|
|
422
|
+
* @throws UpshiftSDKError when the `statusOf` read fails.
|
|
423
|
+
* @worstCaseRpcCalls 1
|
|
424
|
+
* @example
|
|
425
|
+
* ```ts
|
|
426
|
+
* const status = await upshiftSdk.getKycStatus({ chainId: 1, wallet });
|
|
427
|
+
* ```
|
|
428
|
+
*/
|
|
429
|
+
getKycStatus(options: Omit<IKycWalletOptions, 'rpcUrl'>): Promise<IKycStatus>;
|
|
430
|
+
/**
|
|
431
|
+
* Read a wallet's raw KYC record through this instance's provider for
|
|
432
|
+
* `chainId`. See {@link getKycRecord}.
|
|
433
|
+
*
|
|
434
|
+
* @param options - `chainId` and `wallet`.
|
|
435
|
+
* @returns The wallet's {@link IKycRecord}.
|
|
436
|
+
* @throws UpshiftValidationError (`INVALID_CHAIN`) when no provider is
|
|
437
|
+
* configured or no registry is deployed for `chainId`;
|
|
438
|
+
* (`INVALID_ADDRESS`) for a malformed wallet.
|
|
439
|
+
* @throws UpshiftSDKError when the `getRecord` read fails.
|
|
440
|
+
* @worstCaseRpcCalls 1
|
|
441
|
+
* @example
|
|
442
|
+
* ```ts
|
|
443
|
+
* const record = await upshiftSdk.getKycRecord({ chainId: 1, wallet });
|
|
444
|
+
* ```
|
|
445
|
+
*/
|
|
446
|
+
getKycRecord(options: Omit<IKycWalletOptions, 'rpcUrl'>): Promise<IKycRecord>;
|
|
411
447
|
/**
|
|
412
448
|
* @function getStakingPositions gets all available reward staking positions
|
|
413
449
|
* @param wallet optionally passed user wallet address
|