@lifi/perps-sdk-provider-lighter 29.1.0 → 30.0.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/dist/cjs/LighterProvider.d.ts.map +1 -1
- package/dist/cjs/LighterProvider.js +59 -3
- package/dist/cjs/LighterProvider.js.map +1 -1
- package/dist/cjs/accountConfig.d.ts +4 -2
- package/dist/cjs/accountConfig.d.ts.map +1 -1
- package/dist/cjs/accountConfig.js +24 -17
- package/dist/cjs/accountConfig.js.map +1 -1
- package/dist/cjs/signers/LighterSigner.d.ts +1 -0
- package/dist/cjs/signers/LighterSigner.d.ts.map +1 -1
- package/dist/cjs/signers/LighterSigner.js +22 -0
- package/dist/cjs/signers/LighterSigner.js.map +1 -1
- package/dist/cjs/signers/signActions.d.ts.map +1 -1
- package/dist/cjs/signers/signActions.js +2 -1
- package/dist/cjs/signers/signActions.js.map +1 -1
- package/dist/cjs/utils/lighterErrorCode.d.ts.map +1 -1
- package/dist/cjs/utils/lighterErrorCode.js +1 -0
- package/dist/cjs/utils/lighterErrorCode.js.map +1 -1
- package/dist/esm/LighterProvider.d.ts.map +1 -1
- package/dist/esm/LighterProvider.js +67 -4
- package/dist/esm/LighterProvider.js.map +1 -1
- package/dist/esm/accountConfig.d.ts +14 -8
- package/dist/esm/accountConfig.d.ts.map +1 -1
- package/dist/esm/accountConfig.js +38 -39
- package/dist/esm/accountConfig.js.map +1 -1
- package/dist/esm/signers/LighterSigner.d.ts +1 -0
- package/dist/esm/signers/LighterSigner.d.ts.map +1 -1
- package/dist/esm/signers/LighterSigner.js +22 -0
- package/dist/esm/signers/LighterSigner.js.map +1 -1
- package/dist/esm/signers/signActions.d.ts.map +1 -1
- package/dist/esm/signers/signActions.js +4 -2
- package/dist/esm/signers/signActions.js.map +1 -1
- package/dist/esm/utils/lighterErrorCode.d.ts.map +1 -1
- package/dist/esm/utils/lighterErrorCode.js +2 -0
- package/dist/esm/utils/lighterErrorCode.js.map +1 -1
- package/dist/types/LighterProvider.d.ts.map +1 -1
- package/dist/types/accountConfig.d.ts +14 -8
- package/dist/types/accountConfig.d.ts.map +1 -1
- package/dist/types/signers/LighterSigner.d.ts +1 -0
- package/dist/types/signers/LighterSigner.d.ts.map +1 -1
- package/dist/types/signers/signActions.d.ts.map +1 -1
- package/dist/types/utils/lighterErrorCode.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/LighterProvider.ts +101 -7
- package/src/accountConfig.ts +48 -46
- package/src/signers/LighterSigner.ts +47 -0
- package/src/signers/signActions.ts +4 -2
- package/src/utils/lighterErrorCode.ts +2 -0
package/src/accountConfig.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { PerpsError } from '@lifi/perps-sdk'
|
|
1
|
+
import { isSetupOptionFor, PerpsError } from '@lifi/perps-sdk'
|
|
2
2
|
import type {
|
|
3
3
|
AccountConfigSetting,
|
|
4
4
|
LighterAccountConfig,
|
|
5
|
-
|
|
5
|
+
SetupAction,
|
|
6
6
|
} from '@lifi/perps-types'
|
|
7
7
|
import { ActionType, PerpsErrorCode } from '@lifi/perps-types'
|
|
8
8
|
import {
|
|
@@ -16,8 +16,8 @@ function assertNever(value: never): never {
|
|
|
16
16
|
)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
// Wire strings match the backend
|
|
20
|
-
// int projects to null.
|
|
19
|
+
// Wire strings match the modes the backend's ACCOUNT_MODE options bind. An
|
|
20
|
+
// unmapped int projects to null.
|
|
21
21
|
const ACCOUNT_MODE_INT_TO_WIRE: Readonly<Record<number, string>> = {
|
|
22
22
|
[LT_ACCOUNT_TRADING_MODE_SIMPLE]: 'simpleTradingAccount',
|
|
23
23
|
[LT_ACCOUNT_TRADING_MODE_UNIFIED]: 'unifiedTradingAccount',
|
|
@@ -25,28 +25,32 @@ const ACCOUNT_MODE_INT_TO_WIRE: Readonly<Record<number, string>> = {
|
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* Resolve the account tier to the wire string `changeAccountTier` accepts.
|
|
28
|
-
* `userTierName` decides it, but only when
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* unauthenticated read reaches no `/accountLimits` and so carries no tier
|
|
33
|
-
* string, which projects `null` as well: `config.accountType` is Lighter's
|
|
34
|
-
* `SubAccountType`, not a tier, so nothing else in the config decides it.
|
|
28
|
+
* `userTierName` decides it, but only when an ACCOUNT_TYPE option binds that
|
|
29
|
+
* tier: Lighter owns that vocabulary, so an unrecognised value resolves `null`
|
|
30
|
+
* instead of a mis-reported tier. An absent `userTierName` (no
|
|
31
|
+
* `/accountLimits` read) resolves `null`.
|
|
35
32
|
*/
|
|
36
|
-
function resolveAccountTier(
|
|
37
|
-
descriptor:
|
|
38
|
-
|
|
33
|
+
export function resolveAccountTier(
|
|
34
|
+
descriptor: SetupAction,
|
|
35
|
+
userTierName: string | undefined
|
|
39
36
|
): string | null {
|
|
40
|
-
const { userTierName } = config
|
|
41
37
|
if (userTierName === undefined) {
|
|
42
38
|
return null
|
|
43
39
|
}
|
|
44
|
-
|
|
45
|
-
return enumerated.some((option) => option.value === userTierName)
|
|
40
|
+
return boundAccountTiers(descriptor).includes(userTierName)
|
|
46
41
|
? userTierName
|
|
47
42
|
: null
|
|
48
43
|
}
|
|
49
44
|
|
|
45
|
+
/** The tiers the ACCOUNT_TYPE step's options bind. */
|
|
46
|
+
export function boundAccountTiers(descriptor: SetupAction): string[] {
|
|
47
|
+
return (descriptor.options ?? []).flatMap((option) =>
|
|
48
|
+
isSetupOptionFor(option, ActionType.ACCOUNT_TYPE)
|
|
49
|
+
? [option.params.tier]
|
|
50
|
+
: []
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
50
54
|
/**
|
|
51
55
|
* Project a single Lighter descriptor against the typed
|
|
52
56
|
* `LighterAccountConfig` into an `AccountConfigSetting`.
|
|
@@ -60,14 +64,14 @@ function resolveAccountTier(
|
|
|
60
64
|
* | SET_REFERRAL | [] (no parameters)
|
|
61
65
|
* | APPROVE_INTEGRATOR | [] (no parameters)
|
|
62
66
|
* | ACCOUNT_MODE | [{ name: 'mode', value: config.accountTradingMode }]
|
|
63
|
-
* | ACCOUNT_TYPE | [{ name: 'tier', value:
|
|
67
|
+
* | ACCOUNT_TYPE | [{ name: 'tier', value: config.userTierName ?? null }]
|
|
64
68
|
*
|
|
65
69
|
* The switch is exhaustive over `ActionType` so enum additions force a
|
|
66
70
|
* compile error in the `default` arm. ActionTypes that are not valid on
|
|
67
|
-
* `Provider.setup`
|
|
71
|
+
* `Provider.setup` throw at runtime.
|
|
68
72
|
*/
|
|
69
73
|
function projectLighterDescriptor(
|
|
70
|
-
descriptor:
|
|
74
|
+
descriptor: SetupAction,
|
|
71
75
|
config: LighterAccountConfig
|
|
72
76
|
): AccountConfigSetting {
|
|
73
77
|
switch (descriptor.type) {
|
|
@@ -106,28 +110,29 @@ function projectLighterDescriptor(
|
|
|
106
110
|
case ActionType.APPROVE_INTEGRATOR:
|
|
107
111
|
return { type: descriptor.type, values: [] }
|
|
108
112
|
|
|
109
|
-
// `mode` decodes the raw `account_trading_mode` integer to the
|
|
110
|
-
//
|
|
113
|
+
// `mode` decodes the raw `account_trading_mode` integer to the wire strings
|
|
114
|
+
// the options bind (`unifiedTradingAccount` / `simpleTradingAccount`).
|
|
111
115
|
// Unrecognised integers project to `null`.
|
|
112
|
-
case ActionType.ACCOUNT_MODE:
|
|
116
|
+
case ActionType.ACCOUNT_MODE: {
|
|
117
|
+
const mode = ACCOUNT_MODE_INT_TO_WIRE[config.accountTradingMode] ?? null
|
|
113
118
|
return {
|
|
114
119
|
type: descriptor.type,
|
|
115
|
-
values: [
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
values: [{ name: 'mode', value: mode }],
|
|
121
|
+
satisfied: (descriptor.options ?? []).some(
|
|
122
|
+
(option) =>
|
|
123
|
+
isSetupOptionFor(option, ActionType.ACCOUNT_MODE) &&
|
|
124
|
+
option.params.mode === mode
|
|
125
|
+
),
|
|
121
126
|
}
|
|
127
|
+
}
|
|
122
128
|
|
|
123
|
-
//
|
|
124
|
-
//
|
|
129
|
+
// `tier` carries the venue's raw tier name even when no option binds it;
|
|
130
|
+
// only a bound tier reads satisfied.
|
|
125
131
|
case ActionType.ACCOUNT_TYPE:
|
|
126
132
|
return {
|
|
127
133
|
type: descriptor.type,
|
|
128
|
-
values: [
|
|
129
|
-
|
|
130
|
-
],
|
|
134
|
+
values: [{ name: 'tier', value: config.userTierName ?? null }],
|
|
135
|
+
satisfied: resolveAccountTier(descriptor, config.userTierName) !== null,
|
|
131
136
|
}
|
|
132
137
|
|
|
133
138
|
case ActionType.APPROVE_AGENT:
|
|
@@ -147,6 +152,7 @@ function projectLighterDescriptor(
|
|
|
147
152
|
case ActionType.UPDATE_POSITION_MARGIN:
|
|
148
153
|
case ActionType.SIWE_LOGIN:
|
|
149
154
|
case ActionType.CREATE_DEPOSIT_ADDRESS:
|
|
155
|
+
case ActionType.ADD_WITHDRAWAL_ADDRESS:
|
|
150
156
|
case ActionType.ACCEPT_PROVIDER_TERMS:
|
|
151
157
|
case ActionType.UPDATE_ASSET_COLLATERAL:
|
|
152
158
|
case ActionType.DEPOSIT:
|
|
@@ -154,11 +160,14 @@ function projectLighterDescriptor(
|
|
|
154
160
|
case ActionType.META_ONBOARD:
|
|
155
161
|
case ActionType.META_CREATE_REFERRAL_CODE:
|
|
156
162
|
case ActionType.SYNC_FEE_ATTRIBUTION:
|
|
163
|
+
case ActionType.REVOKE_BUILDER_FEE:
|
|
164
|
+
case ActionType.REVOKE_SESSION_AGENT:
|
|
165
|
+
case ActionType.REVOKE_INTEGRATOR:
|
|
157
166
|
throw new PerpsError(
|
|
158
167
|
PerpsErrorCode.SDKError,
|
|
159
168
|
`Lighter account-config mapper has no projection for ` +
|
|
160
169
|
`descriptor type '${descriptor.type}' — this ActionType is not ` +
|
|
161
|
-
`valid on Provider.setup
|
|
170
|
+
`valid on Provider.setup for Lighter.`
|
|
162
171
|
)
|
|
163
172
|
|
|
164
173
|
default:
|
|
@@ -167,22 +176,15 @@ function projectLighterDescriptor(
|
|
|
167
176
|
}
|
|
168
177
|
|
|
169
178
|
/**
|
|
170
|
-
* Project the
|
|
179
|
+
* Project the Lighter setup descriptors against the typed
|
|
171
180
|
* `LighterAccountConfig`. Produces exactly one `AccountConfigSetting` per
|
|
172
|
-
* descriptor,
|
|
173
|
-
* the backend emits them).
|
|
181
|
+
* descriptor, preserving the order in which the backend emits them.
|
|
174
182
|
*
|
|
175
|
-
* @param config Typed account state for the Lighter account.
|
|
176
|
-
* @param setup `Provider.setup` array as emitted by `/providers`.
|
|
177
|
-
* @param options `Provider.options` array as emitted by `/providers`.
|
|
178
183
|
* @public
|
|
179
184
|
*/
|
|
180
185
|
export function projectLighterConfigSettings(
|
|
181
186
|
config: LighterAccountConfig,
|
|
182
|
-
setup:
|
|
183
|
-
options: ProviderAction[]
|
|
187
|
+
setup: SetupAction[]
|
|
184
188
|
): AccountConfigSetting[] {
|
|
185
|
-
return
|
|
186
|
-
projectLighterDescriptor(descriptor, config)
|
|
187
|
-
)
|
|
189
|
+
return setup.map((descriptor) => projectLighterDescriptor(descriptor, config))
|
|
188
190
|
}
|
|
@@ -214,12 +214,45 @@ export class LighterSigner {
|
|
|
214
214
|
'required L1 user wallet signature.'
|
|
215
215
|
)
|
|
216
216
|
}
|
|
217
|
+
if (action === ActionType.REVOKE_INTEGRATOR) {
|
|
218
|
+
return this.signRevokeIntegrator(wasmSignParams, context)
|
|
219
|
+
}
|
|
217
220
|
const wasm = await this.ensureLoaded()
|
|
218
221
|
await this.ensureClient(context)
|
|
219
222
|
const result = this.dispatch(wasm, action, wasmSignParams, context)
|
|
220
223
|
return unwrap(result, action)
|
|
221
224
|
}
|
|
222
225
|
|
|
226
|
+
private async signRevokeIntegrator(
|
|
227
|
+
p: Record<string, unknown>,
|
|
228
|
+
ctx: LighterSignerContext
|
|
229
|
+
): Promise<LighterSignedBlob> {
|
|
230
|
+
const integratorAccountIndex = numberField(p, 'integrator_account_index')
|
|
231
|
+
const maxPerpsTakerFee = revokeIntegratorZeroField(p, 'max_perps_taker_fee')
|
|
232
|
+
const maxPerpsMakerFee = revokeIntegratorZeroField(p, 'max_perps_maker_fee')
|
|
233
|
+
const maxSpotTakerFee = revokeIntegratorZeroField(p, 'max_spot_taker_fee')
|
|
234
|
+
const maxSpotMakerFee = revokeIntegratorZeroField(p, 'max_spot_maker_fee')
|
|
235
|
+
const approvalExpiry = revokeIntegratorZeroField(p, 'approval_expiry')
|
|
236
|
+
const nonce = numberField(p, 'nonce')
|
|
237
|
+
const wasm = await this.ensureLoaded()
|
|
238
|
+
await this.ensureClient(ctx)
|
|
239
|
+
return unwrap(
|
|
240
|
+
wasm.SignApproveIntegrator(
|
|
241
|
+
integratorAccountIndex,
|
|
242
|
+
maxPerpsTakerFee,
|
|
243
|
+
maxPerpsMakerFee,
|
|
244
|
+
maxSpotTakerFee,
|
|
245
|
+
maxSpotMakerFee,
|
|
246
|
+
approvalExpiry,
|
|
247
|
+
SKIP_NONCE_DISABLED,
|
|
248
|
+
nonce,
|
|
249
|
+
ctx.apiKeyIndex,
|
|
250
|
+
ctx.accountIndex
|
|
251
|
+
),
|
|
252
|
+
ActionType.REVOKE_INTEGRATOR
|
|
253
|
+
)
|
|
254
|
+
}
|
|
255
|
+
|
|
223
256
|
/**
|
|
224
257
|
* Step 1 of the REGISTER_API_KEY flow. Generates the WASM blob for a
|
|
225
258
|
* ChangePubKey tx with `L1Sig` left empty, plus the canonical EIP-191
|
|
@@ -738,6 +771,20 @@ function numberField(p: Record<string, unknown>, key: string): number {
|
|
|
738
771
|
)
|
|
739
772
|
}
|
|
740
773
|
|
|
774
|
+
function revokeIntegratorZeroField(
|
|
775
|
+
p: Record<string, unknown>,
|
|
776
|
+
key: string
|
|
777
|
+
): number {
|
|
778
|
+
const value = numberField(p, key)
|
|
779
|
+
if (value !== 0) {
|
|
780
|
+
throw new PerpsError(
|
|
781
|
+
PerpsErrorCode.ValidationError,
|
|
782
|
+
`Lighter REVOKE_INTEGRATOR requires '${key}' to be zero`
|
|
783
|
+
)
|
|
784
|
+
}
|
|
785
|
+
return value
|
|
786
|
+
}
|
|
787
|
+
|
|
741
788
|
function optionalNumberField(
|
|
742
789
|
p: Record<string, unknown>,
|
|
743
790
|
key: string,
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from '../constants.js'
|
|
18
18
|
import type { ApiParams, LighterApiClient } from '../utils/apiClient.js'
|
|
19
19
|
import { fetchAppliedReferralCode } from '../utils/appliedReferralCode.js'
|
|
20
|
+
import { lighterErrorCodeFromBody } from '../utils/lighterErrorCode.js'
|
|
20
21
|
import {
|
|
21
22
|
fetchRegisteredApiKey,
|
|
22
23
|
type LighterRegisteredApiKey,
|
|
@@ -472,7 +473,8 @@ async function signTransfer(
|
|
|
472
473
|
* skips the POST when the account carries one, and a
|
|
473
474
|
* {@link LIGHTER_REFERRAL_ALREADY_USED_CODE} verdict from the POST settles the
|
|
474
475
|
* step the same way. Every other non-success verdict surfaces Lighter's
|
|
475
|
-
* `code`/`message` verbatim
|
|
476
|
+
* `code`/`message` verbatim, under the `PerpsErrorCode` the body code names
|
|
477
|
+
* ({@link lighterErrorCodeFromBody}) or {@link PerpsErrorCode.ExchangeRejected}.
|
|
476
478
|
*/
|
|
477
479
|
async function executeTokenAuthMutation(
|
|
478
480
|
deps: LighterSignActionsDeps,
|
|
@@ -517,7 +519,7 @@ async function executeTokenAuthMutation(
|
|
|
517
519
|
) {
|
|
518
520
|
const suffix = data?.message ? `: ${data.message}` : ''
|
|
519
521
|
throw new PerpsError(
|
|
520
|
-
PerpsErrorCode.ExchangeRejected,
|
|
522
|
+
lighterErrorCodeFromBody(code) ?? PerpsErrorCode.ExchangeRejected,
|
|
521
523
|
`Lighter ${step.action} rejected (code ${code ?? status})${suffix}`
|
|
522
524
|
)
|
|
523
525
|
}
|
|
@@ -16,6 +16,8 @@ const LIGHTER_BODY_ERROR_CODES: ReadonlyMap<number, PerpsErrorCode> = new Map([
|
|
|
16
16
|
[21507, PerpsErrorCode.InsufficientMargin],
|
|
17
17
|
// account is below initial margin
|
|
18
18
|
[21508, PerpsErrorCode.InsufficientMargin],
|
|
19
|
+
// account is not eligible for this operation
|
|
20
|
+
[21520, PerpsErrorCode.SetupRequired],
|
|
19
21
|
// not enough margin to create the order
|
|
20
22
|
[21739, PerpsErrorCode.InsufficientMargin],
|
|
21
23
|
])
|