@cubee_ee/sdk 0.2.3 → 0.2.5
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/clients/CubeBackendClient.d.ts +59 -1
- package/dist/clients/CubeBackendClient.d.ts.map +1 -1
- package/dist/clients/CubeBackendClient.js +104 -4
- package/dist/clients/CubeBackendClient.js.map +1 -1
- package/dist/idl/cubic_pool.json +1101 -114
- package/dist/idl/index.d.ts +242 -2
- package/dist/idl/index.d.ts.map +1 -1
- package/dist/types/result.d.ts +1 -1
- package/dist/types/result.d.ts.map +1 -1
- package/dist/types/result.js.map +1 -1
- package/package.json +1 -1
- package/src/clients/CubeBackendClient.ts +156 -4
- package/src/idl/cubic_pool.json +1101 -114
- package/src/types/result.ts +1 -0
package/dist/idl/index.d.ts
CHANGED
|
@@ -98,6 +98,91 @@ export declare const CUBIC_POOL_IDL: {
|
|
|
98
98
|
name: string;
|
|
99
99
|
type: string;
|
|
100
100
|
})[];
|
|
101
|
+
} | {
|
|
102
|
+
name: string;
|
|
103
|
+
docs: string[];
|
|
104
|
+
discriminator: number[];
|
|
105
|
+
accounts: ({
|
|
106
|
+
name: string;
|
|
107
|
+
docs: string[];
|
|
108
|
+
writable: boolean;
|
|
109
|
+
signer?: undefined;
|
|
110
|
+
} | {
|
|
111
|
+
name: string;
|
|
112
|
+
docs: string[];
|
|
113
|
+
writable?: undefined;
|
|
114
|
+
signer?: undefined;
|
|
115
|
+
} | {
|
|
116
|
+
name: string;
|
|
117
|
+
docs: string[];
|
|
118
|
+
signer: boolean;
|
|
119
|
+
writable?: undefined;
|
|
120
|
+
} | {
|
|
121
|
+
name: string;
|
|
122
|
+
docs: string[];
|
|
123
|
+
writable: boolean;
|
|
124
|
+
signer: boolean;
|
|
125
|
+
} | {
|
|
126
|
+
name: string;
|
|
127
|
+
docs?: undefined;
|
|
128
|
+
writable?: undefined;
|
|
129
|
+
signer?: undefined;
|
|
130
|
+
})[];
|
|
131
|
+
args: {
|
|
132
|
+
name: string;
|
|
133
|
+
type: string;
|
|
134
|
+
}[];
|
|
135
|
+
} | {
|
|
136
|
+
name: string;
|
|
137
|
+
docs: string[];
|
|
138
|
+
discriminator: number[];
|
|
139
|
+
accounts: ({
|
|
140
|
+
name: string;
|
|
141
|
+
writable: boolean;
|
|
142
|
+
docs?: undefined;
|
|
143
|
+
signer?: undefined;
|
|
144
|
+
} | {
|
|
145
|
+
name: string;
|
|
146
|
+
docs: string[];
|
|
147
|
+
writable?: undefined;
|
|
148
|
+
signer?: undefined;
|
|
149
|
+
} | {
|
|
150
|
+
name: string;
|
|
151
|
+
docs: string[];
|
|
152
|
+
writable: boolean;
|
|
153
|
+
signer: boolean;
|
|
154
|
+
} | {
|
|
155
|
+
name: string;
|
|
156
|
+
writable?: undefined;
|
|
157
|
+
docs?: undefined;
|
|
158
|
+
signer?: undefined;
|
|
159
|
+
})[];
|
|
160
|
+
args: never[];
|
|
161
|
+
} | {
|
|
162
|
+
name: string;
|
|
163
|
+
docs: string[];
|
|
164
|
+
discriminator: number[];
|
|
165
|
+
accounts: ({
|
|
166
|
+
name: string;
|
|
167
|
+
docs: string[];
|
|
168
|
+
writable: boolean;
|
|
169
|
+
signer?: undefined;
|
|
170
|
+
} | {
|
|
171
|
+
name: string;
|
|
172
|
+
signer: boolean;
|
|
173
|
+
docs?: undefined;
|
|
174
|
+
writable?: undefined;
|
|
175
|
+
})[];
|
|
176
|
+
args: {
|
|
177
|
+
name: string;
|
|
178
|
+
type: {
|
|
179
|
+
vec: {
|
|
180
|
+
defined: {
|
|
181
|
+
name: string;
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
}[];
|
|
101
186
|
} | {
|
|
102
187
|
name: string;
|
|
103
188
|
docs: string[];
|
|
@@ -184,6 +269,37 @@ export declare const CUBIC_POOL_IDL: {
|
|
|
184
269
|
};
|
|
185
270
|
})[];
|
|
186
271
|
};
|
|
272
|
+
} | {
|
|
273
|
+
name: string;
|
|
274
|
+
type: {
|
|
275
|
+
kind: string;
|
|
276
|
+
fields: ({
|
|
277
|
+
name: string;
|
|
278
|
+
docs: string[];
|
|
279
|
+
type: string;
|
|
280
|
+
} | {
|
|
281
|
+
name: string;
|
|
282
|
+
type: string;
|
|
283
|
+
docs?: undefined;
|
|
284
|
+
} | {
|
|
285
|
+
name: string;
|
|
286
|
+
docs: string[];
|
|
287
|
+
type: {
|
|
288
|
+
array: (number | {
|
|
289
|
+
defined: {
|
|
290
|
+
name: string;
|
|
291
|
+
};
|
|
292
|
+
})[];
|
|
293
|
+
};
|
|
294
|
+
} | {
|
|
295
|
+
name: string;
|
|
296
|
+
docs: string[];
|
|
297
|
+
type: {
|
|
298
|
+
array: (string | number)[];
|
|
299
|
+
};
|
|
300
|
+
})[];
|
|
301
|
+
};
|
|
302
|
+
docs?: undefined;
|
|
187
303
|
} | {
|
|
188
304
|
name: string;
|
|
189
305
|
docs: string[];
|
|
@@ -205,7 +321,11 @@ export declare const CUBIC_POOL_IDL: {
|
|
|
205
321
|
kind: string;
|
|
206
322
|
fields: {
|
|
207
323
|
name: string;
|
|
208
|
-
type:
|
|
324
|
+
type: {
|
|
325
|
+
defined: {
|
|
326
|
+
name: string;
|
|
327
|
+
};
|
|
328
|
+
};
|
|
209
329
|
}[];
|
|
210
330
|
};
|
|
211
331
|
docs?: undefined;
|
|
@@ -652,6 +772,91 @@ export declare const IDLS: {
|
|
|
652
772
|
name: string;
|
|
653
773
|
type: string;
|
|
654
774
|
})[];
|
|
775
|
+
} | {
|
|
776
|
+
name: string;
|
|
777
|
+
docs: string[];
|
|
778
|
+
discriminator: number[];
|
|
779
|
+
accounts: ({
|
|
780
|
+
name: string;
|
|
781
|
+
docs: string[];
|
|
782
|
+
writable: boolean;
|
|
783
|
+
signer?: undefined;
|
|
784
|
+
} | {
|
|
785
|
+
name: string;
|
|
786
|
+
docs: string[];
|
|
787
|
+
writable?: undefined;
|
|
788
|
+
signer?: undefined;
|
|
789
|
+
} | {
|
|
790
|
+
name: string;
|
|
791
|
+
docs: string[];
|
|
792
|
+
signer: boolean;
|
|
793
|
+
writable?: undefined;
|
|
794
|
+
} | {
|
|
795
|
+
name: string;
|
|
796
|
+
docs: string[];
|
|
797
|
+
writable: boolean;
|
|
798
|
+
signer: boolean;
|
|
799
|
+
} | {
|
|
800
|
+
name: string;
|
|
801
|
+
docs?: undefined;
|
|
802
|
+
writable?: undefined;
|
|
803
|
+
signer?: undefined;
|
|
804
|
+
})[];
|
|
805
|
+
args: {
|
|
806
|
+
name: string;
|
|
807
|
+
type: string;
|
|
808
|
+
}[];
|
|
809
|
+
} | {
|
|
810
|
+
name: string;
|
|
811
|
+
docs: string[];
|
|
812
|
+
discriminator: number[];
|
|
813
|
+
accounts: ({
|
|
814
|
+
name: string;
|
|
815
|
+
writable: boolean;
|
|
816
|
+
docs?: undefined;
|
|
817
|
+
signer?: undefined;
|
|
818
|
+
} | {
|
|
819
|
+
name: string;
|
|
820
|
+
docs: string[];
|
|
821
|
+
writable?: undefined;
|
|
822
|
+
signer?: undefined;
|
|
823
|
+
} | {
|
|
824
|
+
name: string;
|
|
825
|
+
docs: string[];
|
|
826
|
+
writable: boolean;
|
|
827
|
+
signer: boolean;
|
|
828
|
+
} | {
|
|
829
|
+
name: string;
|
|
830
|
+
writable?: undefined;
|
|
831
|
+
docs?: undefined;
|
|
832
|
+
signer?: undefined;
|
|
833
|
+
})[];
|
|
834
|
+
args: never[];
|
|
835
|
+
} | {
|
|
836
|
+
name: string;
|
|
837
|
+
docs: string[];
|
|
838
|
+
discriminator: number[];
|
|
839
|
+
accounts: ({
|
|
840
|
+
name: string;
|
|
841
|
+
docs: string[];
|
|
842
|
+
writable: boolean;
|
|
843
|
+
signer?: undefined;
|
|
844
|
+
} | {
|
|
845
|
+
name: string;
|
|
846
|
+
signer: boolean;
|
|
847
|
+
docs?: undefined;
|
|
848
|
+
writable?: undefined;
|
|
849
|
+
})[];
|
|
850
|
+
args: {
|
|
851
|
+
name: string;
|
|
852
|
+
type: {
|
|
853
|
+
vec: {
|
|
854
|
+
defined: {
|
|
855
|
+
name: string;
|
|
856
|
+
};
|
|
857
|
+
};
|
|
858
|
+
};
|
|
859
|
+
}[];
|
|
655
860
|
} | {
|
|
656
861
|
name: string;
|
|
657
862
|
docs: string[];
|
|
@@ -738,6 +943,37 @@ export declare const IDLS: {
|
|
|
738
943
|
};
|
|
739
944
|
})[];
|
|
740
945
|
};
|
|
946
|
+
} | {
|
|
947
|
+
name: string;
|
|
948
|
+
type: {
|
|
949
|
+
kind: string;
|
|
950
|
+
fields: ({
|
|
951
|
+
name: string;
|
|
952
|
+
docs: string[];
|
|
953
|
+
type: string;
|
|
954
|
+
} | {
|
|
955
|
+
name: string;
|
|
956
|
+
type: string;
|
|
957
|
+
docs?: undefined;
|
|
958
|
+
} | {
|
|
959
|
+
name: string;
|
|
960
|
+
docs: string[];
|
|
961
|
+
type: {
|
|
962
|
+
array: (number | {
|
|
963
|
+
defined: {
|
|
964
|
+
name: string;
|
|
965
|
+
};
|
|
966
|
+
})[];
|
|
967
|
+
};
|
|
968
|
+
} | {
|
|
969
|
+
name: string;
|
|
970
|
+
docs: string[];
|
|
971
|
+
type: {
|
|
972
|
+
array: (string | number)[];
|
|
973
|
+
};
|
|
974
|
+
})[];
|
|
975
|
+
};
|
|
976
|
+
docs?: undefined;
|
|
741
977
|
} | {
|
|
742
978
|
name: string;
|
|
743
979
|
docs: string[];
|
|
@@ -759,7 +995,11 @@ export declare const IDLS: {
|
|
|
759
995
|
kind: string;
|
|
760
996
|
fields: {
|
|
761
997
|
name: string;
|
|
762
|
-
type:
|
|
998
|
+
type: {
|
|
999
|
+
defined: {
|
|
1000
|
+
name: string;
|
|
1001
|
+
};
|
|
1002
|
+
};
|
|
763
1003
|
}[];
|
|
764
1004
|
};
|
|
765
1005
|
docs?: undefined;
|
package/dist/idl/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/idl/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/idl/index.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAe,CAAC;AAC3C,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAmB,CAAC;AACnD,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAA0B,CAAC;AAElE,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAIP,CAAC"}
|
package/dist/types/result.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface SdkError {
|
|
|
17
17
|
/** Original error for debugging; never render this to end users. */
|
|
18
18
|
cause?: unknown;
|
|
19
19
|
}
|
|
20
|
-
export type SdkErrorCode = "rpc_unavailable" | "rpc_timeout" | "rpc_rate_limited" | "account_not_found" | "invalid_input" | "math_overflow" | "parse_failure" | "backend_unavailable" | "backend_invalid_response" | "insufficient_funds" | "pool_disabled" | "swaps_disabled" | "unsupported_pool_state" | "slippage_exceeded" | "simulation_failed" | "tx_build_failed" | "alt_fetch_failed" | "unknown";
|
|
20
|
+
export type SdkErrorCode = "rpc_unavailable" | "rpc_timeout" | "rpc_rate_limited" | "account_not_found" | "invalid_input" | "math_overflow" | "parse_failure" | "backend_unavailable" | "backend_invalid_response" | "insufficient_funds" | "pool_disabled" | "swaps_disabled" | "unsupported_pool_state" | "slippage_exceeded" | "simulation_failed" | "tx_build_failed" | "alt_fetch_failed" | "auth_failed" | "unknown";
|
|
21
21
|
export declare const ok: <T>(data: T) => SdkResult<T>;
|
|
22
22
|
export declare const err: (code: SdkErrorCode, humanMessage: string, cause?: unknown) => SdkResult<never>;
|
|
23
23
|
//# sourceMappingURL=result.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/types/result.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GACrB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEnC,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,aAAa,GACb,kBAAkB,GAClB,mBAAmB,GACnB,eAAe,GACf,eAAe,GACf,eAAe,GACf,qBAAqB,GACrB,0BAA0B,GAC1B,oBAAoB,GACpB,eAAe,GACf,gBAAgB,GAChB,wBAAwB,GACxB,mBAAmB,GACnB,mBAAmB,GACnB,iBAAiB,GACjB,kBAAkB,GAClB,SAAS,CAAC;AAEd,eAAO,MAAM,EAAE,GAAI,CAAC,EAAE,MAAM,CAAC,KAAG,SAAS,CAAC,CAAC,CAAyB,CAAC;AACrE,eAAO,MAAM,GAAG,GACd,MAAM,YAAY,EAClB,cAAc,MAAM,EACpB,QAAQ,OAAO,KACd,SAAS,CAAC,KAAK,CAGhB,CAAC"}
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/types/result.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,SAAS,CAAC,CAAC,IACnB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GACrB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEnC,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,IAAI,EAAE,YAAY,CAAC;IACnB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,aAAa,GACb,kBAAkB,GAClB,mBAAmB,GACnB,eAAe,GACf,eAAe,GACf,eAAe,GACf,qBAAqB,GACrB,0BAA0B,GAC1B,oBAAoB,GACpB,eAAe,GACf,gBAAgB,GAChB,wBAAwB,GACxB,mBAAmB,GACnB,mBAAmB,GACnB,iBAAiB,GACjB,kBAAkB,GAClB,aAAa,GACb,SAAS,CAAC;AAEd,eAAO,MAAM,EAAE,GAAI,CAAC,EAAE,MAAM,CAAC,KAAG,SAAS,CAAC,CAAC,CAAyB,CAAC;AACrE,eAAO,MAAM,GAAG,GACd,MAAM,YAAY,EAClB,cAAc,MAAM,EACpB,QAAQ,OAAO,KACd,SAAS,CAAC,KAAK,CAGhB,CAAC"}
|
package/dist/types/result.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/types/result.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/types/result.ts"],"names":[],"mappings":";;;AAsCO,MAAM,EAAE,GAAG,CAAI,IAAO,EAAgB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAAxD,QAAA,EAAE,MAAsD;AAC9D,MAAM,GAAG,GAAG,CACjB,IAAkB,EAClB,YAAoB,EACpB,KAAe,EACG,EAAE,CAAC,CAAC;IACtB,EAAE,EAAE,KAAK;IACT,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE;CACrC,CAAC,CAAC;AAPU,QAAA,GAAG,OAOb"}
|
package/package.json
CHANGED
|
@@ -6,6 +6,16 @@ export interface CubeBackendClientParams {
|
|
|
6
6
|
apiEndpoint: string;
|
|
7
7
|
apiKey?: string;
|
|
8
8
|
defaultHeaders?: Record<string, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Called when tokens are refreshed automatically after a 401.
|
|
11
|
+
* The frontend should persist the new tokens (e.g. to localStorage).
|
|
12
|
+
*/
|
|
13
|
+
onTokenRefreshed?: (tokens: AuthTokens) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Called when both access and refresh tokens are expired/invalid.
|
|
16
|
+
* The frontend should trigger a full re-authentication (SIWS sign-in).
|
|
17
|
+
*/
|
|
18
|
+
onAuthExpired?: () => void;
|
|
9
19
|
}
|
|
10
20
|
|
|
11
21
|
export type StatsKind =
|
|
@@ -131,14 +141,36 @@ export interface LeaderboardEpochResponse {
|
|
|
131
141
|
epochs: EpochHistoryEntry[];
|
|
132
142
|
}
|
|
133
143
|
|
|
144
|
+
// ── Auth types ──
|
|
145
|
+
|
|
146
|
+
export interface NonceResponse {
|
|
147
|
+
nonce: string;
|
|
148
|
+
message: string;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface AuthTokens {
|
|
152
|
+
accessToken: string;
|
|
153
|
+
refreshToken: string;
|
|
154
|
+
wallet: string;
|
|
155
|
+
expiresIn: string;
|
|
156
|
+
}
|
|
157
|
+
|
|
134
158
|
/**
|
|
135
159
|
* REST wrapper around the Cube backend. Every method is a SdkResult; no
|
|
136
160
|
* exceptions escape. If a request fails, the result carries a
|
|
137
161
|
* human-readable error plus the original cause.
|
|
162
|
+
*
|
|
163
|
+
* Auto-refresh: when a request gets 401, the client automatically tries
|
|
164
|
+
* to refresh tokens via POST /api/auth/refresh. If successful, the
|
|
165
|
+
* original request is retried once with the new access token.
|
|
138
166
|
*/
|
|
139
167
|
export class CubeBackendClient {
|
|
140
168
|
private readonly endpoint: string;
|
|
141
169
|
private readonly headers: Record<string, string>;
|
|
170
|
+
private refreshToken: string | null = null;
|
|
171
|
+
private refreshInFlight: Promise<boolean> | null = null;
|
|
172
|
+
private readonly onTokenRefreshed?: (tokens: AuthTokens) => void;
|
|
173
|
+
private readonly onAuthExpired?: () => void;
|
|
142
174
|
|
|
143
175
|
constructor(params: CubeBackendClientParams) {
|
|
144
176
|
this.endpoint = params.apiEndpoint.replace(/\/$/, "");
|
|
@@ -147,6 +179,8 @@ export class CubeBackendClient {
|
|
|
147
179
|
...(params.apiKey ? { Authorization: `Bearer ${params.apiKey}` } : {}),
|
|
148
180
|
...(params.defaultHeaders ?? {}),
|
|
149
181
|
};
|
|
182
|
+
this.onTokenRefreshed = params.onTokenRefreshed;
|
|
183
|
+
this.onAuthExpired = params.onAuthExpired;
|
|
150
184
|
}
|
|
151
185
|
|
|
152
186
|
listPools(): Promise<SdkResult<PoolSummary[]>> {
|
|
@@ -280,16 +314,90 @@ export class CubeBackendClient {
|
|
|
280
314
|
return this.get<StatsSeries>(`/api/stats/${kind}?${qs.toString()}`);
|
|
281
315
|
}
|
|
282
316
|
|
|
317
|
+
// ── Auth ──
|
|
318
|
+
|
|
319
|
+
/** Request a SIWS nonce + pre-built message for the given wallet. */
|
|
320
|
+
getNonce(wallet: string): Promise<SdkResult<NonceResponse>> {
|
|
321
|
+
return this.get<NonceResponse>(
|
|
322
|
+
`/api/auth/nonce?wallet=${encodeURIComponent(wallet)}`,
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/** Submit signed SIWS message to receive access + refresh tokens. */
|
|
327
|
+
verifySignature(
|
|
328
|
+
message: string,
|
|
329
|
+
signature: string,
|
|
330
|
+
): Promise<SdkResult<AuthTokens>> {
|
|
331
|
+
return this.post<AuthTokens>("/api/auth/verify", {
|
|
332
|
+
message,
|
|
333
|
+
signature,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Set both tokens. Call this after verifySignature() and on app init
|
|
339
|
+
* (restoring tokens from storage).
|
|
340
|
+
*/
|
|
341
|
+
setTokens(accessToken: string, refreshToken: string): void {
|
|
342
|
+
this.headers["Authorization"] = `Bearer ${accessToken}`;
|
|
343
|
+
this.refreshToken = refreshToken;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/** Clear both tokens (logout). */
|
|
347
|
+
clearTokens(): void {
|
|
348
|
+
delete this.headers["Authorization"];
|
|
349
|
+
this.refreshToken = null;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/** @deprecated Use setTokens() instead. */
|
|
353
|
+
setAccessToken(token: string): void {
|
|
354
|
+
this.headers["Authorization"] = `Bearer ${token}`;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/** @deprecated Use clearTokens() instead. */
|
|
358
|
+
clearAccessToken(): void {
|
|
359
|
+
delete this.headers["Authorization"];
|
|
360
|
+
this.refreshToken = null;
|
|
361
|
+
}
|
|
362
|
+
|
|
283
363
|
/** Generic GET with retry. Callers that need it for other endpoints. */
|
|
284
364
|
get<T>(path: string): Promise<SdkResult<T>> {
|
|
285
|
-
return this.
|
|
365
|
+
return this.requestWithRefresh<T>("GET", path);
|
|
286
366
|
}
|
|
287
367
|
|
|
288
368
|
post<T>(path: string, body: unknown): Promise<SdkResult<T>> {
|
|
289
|
-
return this.
|
|
369
|
+
return this.requestWithRefresh<T>("POST", path, body);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// ── Private: HTTP layer with auto-refresh ──
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Core request method with auto-refresh on 401.
|
|
376
|
+
* If a request gets 401 and we have a refresh token:
|
|
377
|
+
* 1. Call POST /api/auth/refresh (deduplicated if concurrent)
|
|
378
|
+
* 2. On success: update tokens, notify via callback, retry original request
|
|
379
|
+
* 3. On failure: notify via onAuthExpired callback, return original error
|
|
380
|
+
*/
|
|
381
|
+
private async requestWithRefresh<T>(
|
|
382
|
+
method: "GET" | "POST",
|
|
383
|
+
path: string,
|
|
384
|
+
body?: unknown,
|
|
385
|
+
): Promise<SdkResult<T>> {
|
|
386
|
+
const result = await this.rawRequest<T>(method, path, body);
|
|
387
|
+
|
|
388
|
+
// Don't auto-refresh for auth endpoints themselves
|
|
389
|
+
const isAuthPath = path.startsWith("/api/auth/");
|
|
390
|
+
if (!isAuthPath && !result.ok && this.is401(result) && this.refreshToken) {
|
|
391
|
+
const refreshed = await this.tryRefresh();
|
|
392
|
+
if (refreshed) {
|
|
393
|
+
return this.rawRequest<T>(method, path, body);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
return result;
|
|
290
398
|
}
|
|
291
399
|
|
|
292
|
-
private async
|
|
400
|
+
private async rawRequest<T>(
|
|
293
401
|
method: "GET" | "POST",
|
|
294
402
|
path: string,
|
|
295
403
|
body?: unknown
|
|
@@ -303,7 +411,11 @@ export class CubeBackendClient {
|
|
|
303
411
|
const raw = await safeCall(async () => {
|
|
304
412
|
const res = await fetch(url, fetchOpts);
|
|
305
413
|
if (!res.ok) {
|
|
306
|
-
|
|
414
|
+
const error = new Error(
|
|
415
|
+
`${method} ${path} → HTTP ${res.status} ${res.statusText}`,
|
|
416
|
+
);
|
|
417
|
+
(error as any).status = res.status;
|
|
418
|
+
throw error;
|
|
307
419
|
}
|
|
308
420
|
return (await res.json()) as T;
|
|
309
421
|
});
|
|
@@ -311,6 +423,46 @@ export class CubeBackendClient {
|
|
|
311
423
|
return ok(raw.data);
|
|
312
424
|
}
|
|
313
425
|
|
|
426
|
+
/**
|
|
427
|
+
* Attempt to refresh tokens. Returns true if successful.
|
|
428
|
+
* Deduplicates concurrent refresh attempts.
|
|
429
|
+
*/
|
|
430
|
+
private async tryRefresh(): Promise<boolean> {
|
|
431
|
+
// Deduplicate: if a refresh is already in flight, wait for it
|
|
432
|
+
if (this.refreshInFlight) {
|
|
433
|
+
return this.refreshInFlight;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
this.refreshInFlight = this.doRefresh();
|
|
437
|
+
try {
|
|
438
|
+
return await this.refreshInFlight;
|
|
439
|
+
} finally {
|
|
440
|
+
this.refreshInFlight = null;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
private async doRefresh(): Promise<boolean> {
|
|
445
|
+
const res = await this.rawRequest<AuthTokens>("POST", "/api/auth/refresh", {
|
|
446
|
+
refreshToken: this.refreshToken,
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
if (res.ok) {
|
|
450
|
+
this.setTokens(res.data.accessToken, res.data.refreshToken);
|
|
451
|
+
this.onTokenRefreshed?.(res.data);
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Refresh failed — both tokens are dead
|
|
456
|
+
this.clearTokens();
|
|
457
|
+
this.onAuthExpired?.();
|
|
458
|
+
return false;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
private is401(result: SdkResult<unknown>): boolean {
|
|
462
|
+
if (result.ok) return false;
|
|
463
|
+
return result.error.humanMessage.includes("HTTP 401");
|
|
464
|
+
}
|
|
465
|
+
|
|
314
466
|
/**
|
|
315
467
|
* Fetch a response envelope of the form `{ data: T, ... }` and unwrap
|
|
316
468
|
* the `.data` field. The existing Cube backend wraps most endpoints
|