Skip to content

Commit 93d434f

Browse files
authored
Merge main branch (#104)
1 parent 942fc7e commit 93d434f

20 files changed

+304
-56
lines changed

src/contracts/abis/Erc20Abi.json

+94-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,94 @@
1-
[ { "inputs": [ { "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "approve", "outputs": [ { "internalType": "bool", "name": "", "type": "bool" } ], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "account", "type": "address" } ], "name": "balanceOf", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" }, { "inputs": [ { "internalType": "address", "name": "owner", "type": "address" }, { "internalType": "address", "name": "spender", "type": "address" } ], "name": "allowance", "outputs": [ { "internalType": "uint256", "name": "", "type": "uint256" } ], "stateMutability": "view", "type": "function" } ]
1+
[
2+
{
3+
"inputs": [
4+
{
5+
"internalType": "address",
6+
"name": "spender",
7+
"type": "address"
8+
},
9+
{
10+
"internalType": "uint256",
11+
"name": "value",
12+
"type": "uint256"
13+
}
14+
],
15+
"name": "approve",
16+
"outputs": [
17+
{
18+
"internalType": "bool",
19+
"name": "",
20+
"type": "bool"
21+
}
22+
],
23+
"stateMutability": "nonpayable",
24+
"type": "function"
25+
},
26+
{
27+
"inputs": [
28+
{
29+
"internalType": "address",
30+
"name": "account",
31+
"type": "address"
32+
}
33+
],
34+
"name": "balanceOf",
35+
"outputs": [
36+
{
37+
"internalType": "uint256",
38+
"name": "",
39+
"type": "uint256"
40+
}
41+
],
42+
"stateMutability": "view",
43+
"type": "function"
44+
},
45+
{
46+
"anonymous": false,
47+
"inputs": [
48+
{
49+
"indexed": true,
50+
"internalType": "address",
51+
"name": "from",
52+
"type": "address"
53+
},
54+
{
55+
"indexed": true,
56+
"internalType": "address",
57+
"name": "to",
58+
"type": "address"
59+
},
60+
{
61+
"indexed": false,
62+
"internalType": "uint256",
63+
"name": "value",
64+
"type": "uint256"
65+
}
66+
],
67+
"name": "Transfer",
68+
"type": "event"
69+
},
70+
{
71+
"inputs": [
72+
{
73+
"internalType": "address",
74+
"name": "owner",
75+
"type": "address"
76+
},
77+
{
78+
"internalType": "address",
79+
"name": "spender",
80+
"type": "address"
81+
}
82+
],
83+
"name": "allowance",
84+
"outputs": [
85+
{
86+
"internalType": "uint256",
87+
"name": "",
88+
"type": "uint256"
89+
}
90+
],
91+
"stateMutability": "view",
92+
"type": "function"
93+
}
94+
]

src/contracts/abis/index.js

-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import VaultFactoryAbi from './VaultFactoryAbi.json'
1515
import PriceOracleAbi from './PriceOracleAbi.json'
1616
import UniswapPoolAbi from './UniswapPoolAbi.json'
1717
import MulticallAbi from './MulticallAbi.json'
18-
import MintTokenAbi from './MintTokenAbi.json'
1918
import UsdRateAbi from './UsdRateAbi.json'
2019
import KeeperAbi from './KeeperAbi.json'
2120
import VaultAbi from './VaultAbi.json'
@@ -44,7 +43,6 @@ export {
4443
PriceOracleAbi,
4544
UniswapPoolAbi,
4645
MulticallAbi,
47-
MintTokenAbi,
4846
UsdRateAbi,
4947
KeeperAbi,
5048
VaultAbi,

src/contracts/createContracts.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
VaultAbi,
77
KeeperAbi,
88
UsdRateAbi,
9-
MintTokenAbi,
109
MulticallAbi,
1110
UniswapPoolAbi,
1211
PriceOracleAbi,
@@ -68,7 +67,7 @@ const getKeeper = (provider: Provider, config: StakeWise.Config) => createContra
6867

6968
const getMintToken = (provider: Provider, config: StakeWise.Config) => createContract<StakeWise.ABI.MintToken>(
7069
config.addresses.tokens.mintToken,
71-
MintTokenAbi,
70+
Erc20Abi,
7271
provider
7372
)
7473

src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ import './types/global'
33

44
export * from './utils/enums'
55
export { createContract } from './contracts'
6-
export { BigDecimal, configs } from './utils'
76
export { default as StakeWiseSDK } from './StakeWiseSDK'
7+
export { BigDecimal, configs, getGas, createProvider } from './utils'

src/modules/gql-module/abortCallback.ts

+9
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
class AbortCallback {
2+
private isAborted: boolean
23
callback: Promise<any>
34
onAbort: () => void
45

56
constructor(callback: Promise<any>, onAbort: () => void) {
7+
this.isAborted = false
68
this.callback = callback
79
this.onAbort = onAbort
810
}
911

1012
then(onSuccess: (data: any) => any, onError?: (error: any) => any) {
13+
if (this.isAborted) {
14+
const dummyPromise = new Promise(() => {})
15+
16+
return new AbortCallback(dummyPromise, this.onAbort)
17+
}
18+
1119
return new AbortCallback(this.callback.then(onSuccess, onError), this.onAbort)
1220
}
1321

@@ -20,6 +28,7 @@ class AbortCallback {
2028
}
2129

2230
abort() {
31+
this.isAborted = true
2332
this.onAbort()
2433
}
2534
}

src/modules/gql-module/abortPromise.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ const dummyPromise = new Promise(() => {})
1616
class AbortPromise<Data> {
1717
private promise: Promise<Data>
1818
private isAborted: boolean
19+
private onAbort?: () => void
1920

20-
constructor(callback: AbortPromiseCallback<Data>) {
21+
constructor(callback: AbortPromiseCallback<Data>, onAbort?: () => void) {
2122
this.isAborted = false
23+
this.onAbort = onAbort
24+
2225
this.promise = new Promise(callback)
2326
.then((data) => {
2427
try {
@@ -58,6 +61,7 @@ class AbortPromise<Data> {
5861
}
5962
})
6063
}
64+
6165
const allPromises = Promise.all(promises).then((data) => {
6266
if (isAborted) {
6367
return dummyPromise as Promise<T[]>
@@ -95,6 +99,10 @@ class AbortPromise<Data> {
9599

96100
abort() {
97101
this.isAborted = true
102+
103+
if (typeof this.onAbort === 'function') {
104+
this.onAbort()
105+
}
98106
}
99107
}
100108

src/modules/gql-module/abortRequest.ts

+45-29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import AbortCallback from './abortCallback'
1+
import AbortPromise from './abortPromise'
22

33

44
type ModifyCallback<Data, ModifiedData = Data> = (value: Data) => ModifiedData | PromiseLike<ModifiedData>
@@ -7,8 +7,11 @@ type FirstCallback<Data> = (value: Data) => Data | any
77

88
type EmptyCallback = () => void
99

10+
type ErrorCallback<Data, ModifiedData = Data> = (error: Error | any) => Promise<void> | AbortRequest<Data, ModifiedData>
11+
1012
type AbortRequestInit<Data, ModifiedData> = RequestInit & {
1113
onSuccess: ModifyCallback<Data, ModifiedData>
14+
onError?: ErrorCallback<Data, ModifiedData>
1215
}
1316

1417
type PendingRequest = {
@@ -18,19 +21,17 @@ type PendingRequest = {
1821

1922
const requestsQueue: Record<string, PendingRequest | undefined> = {}
2023

21-
const dummyPromise = new Promise(() => {})
22-
2324
// Returns fetch promise that can be aborted
2425
// If we create several promises, only one request will be executed
2526
class AbortRequest<Data, ModifiedData> {
2627
private controller = new AbortController()
2728
request: Promise<Data>
28-
promise: Promise<ModifiedData>
29+
promise: AbortPromise<ModifiedData>
2930
body: string
3031
isAborted: boolean
3132

3233
constructor(url: RequestInfo | URL, abortRequestInit: AbortRequestInit<Data, ModifiedData>) {
33-
const { onSuccess, ...init } = abortRequestInit
34+
const { onSuccess, onError, ...init } = abortRequestInit
3435

3536
this.body = init.body as string
3637
this.isAborted = false
@@ -46,14 +47,34 @@ class AbortRequest<Data, ModifiedData> {
4647
...init,
4748
signal: this.controller.signal,
4849
})
49-
.then((res) => res.json())
50+
.then((response) => {
51+
if (response.ok) {
52+
return response.json()
53+
}
54+
55+
return response.json().then((json) => Promise.reject(json))
56+
})
5057
.then((json) => {
5158
requestsQueue[this.body] = undefined
59+
60+
if (json?.errors) {
61+
throw new Error(json.errors[0].message)
62+
}
63+
64+
// Subgraph encountered indexing errors at some past block
65+
if (json?.data?._meta?.hasIndexingErrors) {
66+
throw new Error('Subgraph indexing error')
67+
}
68+
5269
return json?.data as Data
5370
})
5471
.catch((error) => {
5572
requestsQueue[this.body] = undefined
5673

74+
if (typeof onError === 'function') {
75+
onError(error)
76+
}
77+
5778
return Promise.reject(error)
5879
})
5980

@@ -63,42 +84,37 @@ class AbortRequest<Data, ModifiedData> {
6384
}
6485
}
6586

66-
this.promise = this.request
67-
.then((data) => {
68-
try {
69-
if (this.isAborted) {
70-
return dummyPromise as Promise<ModifiedData>
71-
}
72-
73-
if (typeof onSuccess === 'function') {
74-
return onSuccess(data) as Promise<ModifiedData>
75-
}
87+
this.promise = new AbortPromise<ModifiedData>(async (resolve, reject) => {
88+
try {
89+
const result = await this.request
7690

77-
return data as Promise<ModifiedData>
78-
}
79-
catch (error) {
80-
return Promise.reject(error)
91+
if (typeof onSuccess === 'function') {
92+
return resolve(onSuccess(result) as ModifiedData)
8193
}
82-
})
83-
.catch((error) => {
84-
if (this.isAborted) {
85-
return dummyPromise as Promise<ModifiedData>
94+
95+
return resolve(result as ModifiedData)
96+
}
97+
catch (error) {
98+
if (typeof onError === 'function') {
99+
// ATTN use resolve because onError can return a promise
100+
return resolve(onError(error) as ModifiedData)
86101
}
87102

88-
return Promise.reject(error)
89-
})
103+
return reject(error)
104+
}
105+
}, this.abort.bind(this))
90106
}
91107

92108
then(onSuccess: FirstCallback<ModifiedData>, onError?: FirstCallback<ModifiedData>) {
93-
return new AbortCallback(this.promise.then(onSuccess, onError), this.abort.bind(this))
109+
return this.promise.then(onSuccess, onError)
94110
}
95111

96112
catch(callback: FirstCallback<ModifiedData>) {
97-
return new AbortCallback(this.promise.catch(callback), this.abort.bind(this))
113+
return this.promise.catch(callback)
98114
}
99115

100116
finally(callback: EmptyCallback) {
101-
return new AbortCallback(this.promise.finally(callback), this.abort.bind(this))
117+
return this.promise.finally(callback)
102118
}
103119

104120
abort() {

src/modules/gql-module/graphqlFetch.ts

+24-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
import AbortRequest from './abortRequest'
22
import type { FetchInput } from './types'
3+
import { getRequestUrl, saveErrorUrlToSessionStorage } from './utils'
34

45

6+
type ExtendedFetchInput<Data, Variables, ModifiedData> = FetchInput<Data, Variables, ModifiedData> & {
7+
retryCount?: number
8+
}
9+
510
const graphqlFetch = <Data, Variables, ModifiedData>(
6-
options: FetchInput<Data, Variables, ModifiedData>
11+
options: ExtendedFetchInput<Data, Variables, ModifiedData>
712
): AbortRequest<Data, ModifiedData> => {
8-
const { url, query, variables, modifyResult } = options
13+
const { url, query, variables, retryCount = 0, modifyResult } = options
914

1015
const operationName = query
1116
.replace(/^(query|mutation)\s/, '')
1217
.replace(/[({].*/, '')
1318
.trim()
1419

20+
const currentUrl = getRequestUrl(url)
1521
const opName = operationName ? `?opName=${operationName}` : ''
16-
const requestUrl = `${url}${opName}`
22+
const requestUrl = `${currentUrl}${opName}`
1723

1824
return new AbortRequest<Data, ModifiedData>(requestUrl, {
1925
method: 'POST',
@@ -28,6 +34,21 @@ const graphqlFetch = <Data, Variables, ModifiedData>(
2834
onSuccess: (data: Data) => typeof modifyResult === 'function'
2935
? modifyResult(data)
3036
: data as unknown as ModifiedData,
37+
onError: (error: Error | any) => {
38+
const hasBackupUrl = Array.isArray(url) && url.length > 1
39+
40+
if (hasBackupUrl && retryCount < 1) {
41+
saveErrorUrlToSessionStorage(url[0])
42+
43+
return graphqlFetch({
44+
...options,
45+
url: url[1],
46+
retryCount: retryCount + 1,
47+
})
48+
}
49+
50+
return Promise.reject(error)
51+
},
3152
})
3253
}
3354

0 commit comments

Comments
 (0)