@pioneer-platform/pioneer-sdk 0.0.82 → 4.13.30
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/index.cjs +5358 -0
- package/dist/index.es.js +5537 -0
- package/dist/index.js +5537 -0
- package/package.json +55 -37
- package/src/TransactionManager.ts +333 -0
- package/src/charts/cosmos-staking.ts +171 -0
- package/src/charts/evm.ts +199 -0
- package/src/charts/index.ts +46 -0
- package/src/charts/maya.ts +110 -0
- package/src/charts/types.ts +77 -0
- package/src/charts/utils.ts +24 -0
- package/src/fees/index.ts +620 -0
- package/src/getPubkey.ts +151 -0
- package/src/index.ts +2250 -0
- package/src/kkapi-batch-client.ts +191 -0
- package/src/offline-client.ts +287 -0
- package/src/supportedCaips.ts +36 -0
- package/src/txbuilder/createUnsignedEvmTx.ts +532 -0
- package/src/txbuilder/createUnsignedRippleTx.ts +122 -0
- package/src/txbuilder/createUnsignedStakingTx.ts +188 -0
- package/src/txbuilder/createUnsignedTendermintTx.ts +249 -0
- package/src/txbuilder/createUnsignedUxtoTx.ts +450 -0
- package/src/txbuilder/templates/cosmos-staking.ts +157 -0
- package/src/txbuilder/templates/cosmos.ts +30 -0
- package/src/txbuilder/templates/mayachain.ts +60 -0
- package/src/txbuilder/templates/osmosis.ts +30 -0
- package/src/txbuilder/templates/thorchain.ts +60 -0
- package/src/utils/build-dashboard.ts +181 -0
- package/src/utils/format-time.ts +12 -0
- package/src/utils/kkapi-detection.ts +64 -0
- package/src/utils/pubkey-helpers.ts +75 -0
- package/lib/index.d.ts +0 -66
- package/lib/index.js +0 -493
- package/tsconfig.json +0 -13
package/package.json
CHANGED
@@ -1,43 +1,61 @@
|
|
1
1
|
{
|
2
|
+
"author": "highlander",
|
2
3
|
"name": "@pioneer-platform/pioneer-sdk",
|
3
|
-
"version": "
|
4
|
-
"main": "./lib/index.js",
|
5
|
-
"types": "./lib/index.d.ts",
|
6
|
-
"scripts": {
|
7
|
-
"npm": "npm i",
|
8
|
-
"npm-update": "npm update",
|
9
|
-
"test": "npm run build && node __tests__/test-module.js",
|
10
|
-
"test-ts": "rm -R lib && npm run build && ts-node __tests__/test-module-ts.ts",
|
11
|
-
"lint": "prettier --write '**/**/*.ts'",
|
12
|
-
"start": "nodemon --watch 'src/**/*.ts' --exec ts-node __tests__node",
|
13
|
-
"build": "tsc -p .",
|
14
|
-
"prepublish": "npm run build",
|
15
|
-
"refresh": "rm -rf ./node_modules ./package-lock.json && npm install",
|
16
|
-
"test-jest": "jest --coverage",
|
17
|
-
"test:watch": "jest --coverage --watchAll",
|
18
|
-
"build:watch": "onchange 'src/**/*.ts' -- npm run build",
|
19
|
-
"view:coverage": "serve coverage/lcov-report",
|
20
|
-
"clean": "rm -rf coverage src/**/*.js src/**/*.map lib node_modules"
|
21
|
-
},
|
4
|
+
"version": "4.13.30",
|
22
5
|
"dependencies": {
|
23
|
-
"@
|
24
|
-
"@pioneer-platform/
|
25
|
-
"@pioneer-platform/pioneer-
|
26
|
-
"
|
27
|
-
"
|
28
|
-
"
|
29
|
-
"
|
30
|
-
"
|
6
|
+
"@keepkey/keepkey-sdk": "^0.2.62",
|
7
|
+
"@pioneer-platform/loggerdog": "^8.4.1",
|
8
|
+
"@pioneer-platform/pioneer-caip": "^9.3.1",
|
9
|
+
"@pioneer-platform/pioneer-client": "^9.3.1",
|
10
|
+
"@pioneer-platform/pioneer-coins": "^9.4.1",
|
11
|
+
"@pioneer-platform/pioneer-discovery": "^0.1.1",
|
12
|
+
"@pioneer-platform/pioneer-events": "^8.4.1",
|
13
|
+
"coinselect": "^3.1.13",
|
14
|
+
"eventemitter3": "^5.0.1",
|
15
|
+
"neotraverse": "^0.6.8"
|
31
16
|
},
|
17
|
+
"description": "Pioneer Core SDK",
|
32
18
|
"devDependencies": {
|
33
|
-
"@types/
|
34
|
-
"@types/
|
35
|
-
"@types/
|
36
|
-
"
|
37
|
-
"
|
38
|
-
"
|
39
|
-
"
|
40
|
-
"
|
41
|
-
|
42
|
-
|
19
|
+
"@types/bn.js": "5.1.5",
|
20
|
+
"@types/crypto-js": "4.2.1",
|
21
|
+
"@types/elliptic": "6.4.18",
|
22
|
+
"@types/long": "4.0.2",
|
23
|
+
"@types/node": "20.10.0",
|
24
|
+
"@types/tiny-secp256k1": "1.0.0",
|
25
|
+
"@vitest/coverage-istanbul": "0.34.6",
|
26
|
+
"vitest": "0.34.6"
|
27
|
+
},
|
28
|
+
"eslintConfig": {
|
29
|
+
"extends": "../../../internal/eslint-config"
|
30
|
+
},
|
31
|
+
"exports": {
|
32
|
+
".": {
|
33
|
+
"import": "./dist/index.js",
|
34
|
+
"require": "./dist/index.cjs",
|
35
|
+
"types": "./dist/index.d.ts"
|
36
|
+
}
|
37
|
+
},
|
38
|
+
"files": [
|
39
|
+
"src/",
|
40
|
+
"dist/"
|
41
|
+
],
|
42
|
+
"homepage": "https://github.com/thorswap/SwapKit",
|
43
|
+
"license": "GPL-3.0",
|
44
|
+
"main": "./dist/index.cjs",
|
45
|
+
"module": "./dist/index.es.js",
|
46
|
+
"publishConfig": {
|
47
|
+
"access": "public"
|
48
|
+
},
|
49
|
+
"react-native": "./src/index.ts",
|
50
|
+
"repository": "https://github.com/thorswap/SwapKit.git",
|
51
|
+
"scripts": {
|
52
|
+
"build": "bash scripts/build.sh",
|
53
|
+
"build:watch": "nodemon --watch src --exec 'bun run build'",
|
54
|
+
"clean": "rm -rf dist .turbo node_modules",
|
55
|
+
"lint": "eslint ./ --ext .ts,.tsx --fix; tsc --noEmit",
|
56
|
+
"test": "echo 'vitest --run'",
|
57
|
+
"test:coverage": "echo 'vitest run --coverage'"
|
58
|
+
},
|
59
|
+
"type": "module",
|
60
|
+
"types": "./dist/index.d.ts"
|
43
61
|
}
|
@@ -0,0 +1,333 @@
|
|
1
|
+
/*
|
2
|
+
Tx Manager
|
3
|
+
*/
|
4
|
+
import type EventEmitter from 'events';
|
5
|
+
|
6
|
+
import { CAIP_TO_COIN_MAP, SUPPORTED_CAIPS } from './supportedCaips';
|
7
|
+
import { createUnsignedEvmTx } from './txbuilder/createUnsignedEvmTx';
|
8
|
+
import { createUnsignedRippleTx } from './txbuilder/createUnsignedRippleTx';
|
9
|
+
import { createUnsignedTendermintTx } from './txbuilder/createUnsignedTendermintTx';
|
10
|
+
import { createUnsignedUxtoTx } from './txbuilder/createUnsignedUxtoTx';
|
11
|
+
|
12
|
+
const TAG = ' | Transaction | ';
|
13
|
+
|
14
|
+
interface TransactionDependencies {
|
15
|
+
context: string;
|
16
|
+
assetContext: any;
|
17
|
+
balances: any[];
|
18
|
+
pubkeys: any[];
|
19
|
+
nodes: any[];
|
20
|
+
pioneer: any;
|
21
|
+
keepKeySdk: any;
|
22
|
+
}
|
23
|
+
|
24
|
+
export class TransactionManager {
|
25
|
+
private context: string;
|
26
|
+
private assetContext: any;
|
27
|
+
private balances: any[];
|
28
|
+
private pubkeys: any[];
|
29
|
+
private nodes: any[];
|
30
|
+
private pioneer: any;
|
31
|
+
private keepKeySdk: any;
|
32
|
+
private events: EventEmitter;
|
33
|
+
|
34
|
+
constructor(dependencies: TransactionDependencies, events: EventEmitter) {
|
35
|
+
this.context = dependencies.context;
|
36
|
+
this.assetContext = dependencies.assetContext;
|
37
|
+
this.balances = dependencies.balances;
|
38
|
+
this.pubkeys = dependencies.pubkeys;
|
39
|
+
this.nodes = dependencies.nodes;
|
40
|
+
this.pioneer = dependencies.pioneer;
|
41
|
+
this.keepKeySdk = dependencies.keepKeySdk;
|
42
|
+
this.events = events;
|
43
|
+
}
|
44
|
+
|
45
|
+
async classifyCaip(caip: string): Promise<string> {
|
46
|
+
if (SUPPORTED_CAIPS.UTXO.includes(caip)) return 'UTXO';
|
47
|
+
if (SUPPORTED_CAIPS.TENDERMINT.includes(caip)) return 'TENDERMINT';
|
48
|
+
if (caip.startsWith('eip155')) return 'EIP155';
|
49
|
+
if (SUPPORTED_CAIPS.OTHER.includes(caip)) return 'OTHER';
|
50
|
+
throw new Error(`Unsupported CAIP: ${caip}`);
|
51
|
+
}
|
52
|
+
|
53
|
+
async transfer({ caip, to, amount, memo, isMax = false, feeLevel = 5, changeScriptType }: any): Promise<any> {
|
54
|
+
let tag = TAG + ' | transfer | ';
|
55
|
+
try {
|
56
|
+
if (!this.pioneer) throw Error('Failed to init! pioneer');
|
57
|
+
if (!caip) throw Error('Missing required param! caip');
|
58
|
+
if (!to) throw Error('Missing required param! to');
|
59
|
+
if (!amount) throw Error('Missing required param! amount');
|
60
|
+
if (!memo) memo = ' ';
|
61
|
+
const type = await this.classifyCaip(caip);
|
62
|
+
|
63
|
+
let unsignedTx;
|
64
|
+
switch (type) {
|
65
|
+
case 'UTXO': {
|
66
|
+
unsignedTx = await createUnsignedUxtoTx(
|
67
|
+
caip,
|
68
|
+
to,
|
69
|
+
amount,
|
70
|
+
memo,
|
71
|
+
this.pubkeys,
|
72
|
+
this.pioneer,
|
73
|
+
this.keepKeySdk,
|
74
|
+
isMax,
|
75
|
+
feeLevel,
|
76
|
+
changeScriptType,
|
77
|
+
);
|
78
|
+
break;
|
79
|
+
}
|
80
|
+
case 'TENDERMINT': {
|
81
|
+
const txType = 'transfer';
|
82
|
+
unsignedTx = await createUnsignedTendermintTx(
|
83
|
+
caip,
|
84
|
+
txType,
|
85
|
+
amount,
|
86
|
+
memo,
|
87
|
+
this.pubkeys,
|
88
|
+
this.pioneer,
|
89
|
+
this.keepKeySdk,
|
90
|
+
isMax,
|
91
|
+
to,
|
92
|
+
);
|
93
|
+
break;
|
94
|
+
}
|
95
|
+
case 'EIP155': {
|
96
|
+
unsignedTx = await createUnsignedEvmTx(
|
97
|
+
caip,
|
98
|
+
to,
|
99
|
+
amount,
|
100
|
+
memo,
|
101
|
+
this.pubkeys,
|
102
|
+
this.pioneer,
|
103
|
+
this.keepKeySdk,
|
104
|
+
isMax,
|
105
|
+
feeLevel,
|
106
|
+
);
|
107
|
+
break;
|
108
|
+
}
|
109
|
+
case 'OTHER': {
|
110
|
+
unsignedTx = await createUnsignedRippleTx(
|
111
|
+
caip,
|
112
|
+
to,
|
113
|
+
amount,
|
114
|
+
memo,
|
115
|
+
this.pubkeys,
|
116
|
+
this.pioneer,
|
117
|
+
this.keepKeySdk,
|
118
|
+
isMax,
|
119
|
+
);
|
120
|
+
break;
|
121
|
+
}
|
122
|
+
default: {
|
123
|
+
throw new Error(`Unsupported CAIP: ${caip}`);
|
124
|
+
}
|
125
|
+
}
|
126
|
+
|
127
|
+
return unsignedTx;
|
128
|
+
} catch (e: any) {
|
129
|
+
console.error(tag, e);
|
130
|
+
throw e;
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
async sign({ caip, unsignedTx }: any): Promise<any> {
|
135
|
+
let tag = TAG + ' | sign | ';
|
136
|
+
try {
|
137
|
+
if (!this.pioneer) throw Error('Failed to init! pioneer');
|
138
|
+
|
139
|
+
|
140
|
+
const type = await this.classifyCaip(caip);
|
141
|
+
let signedTx: any;
|
142
|
+
|
143
|
+
switch (type) {
|
144
|
+
case 'UTXO': {
|
145
|
+
const coin = CAIP_TO_COIN_MAP[caip];
|
146
|
+
if (!coin) throw Error(`Unsupported UTXO coin type for CAIP: ${caip}`);
|
147
|
+
|
148
|
+
const signPayload: any = {
|
149
|
+
coin,
|
150
|
+
inputs: unsignedTx.inputs,
|
151
|
+
outputs: unsignedTx.outputs,
|
152
|
+
version: 1,
|
153
|
+
locktime: 0,
|
154
|
+
// opReturnData: unsignedTx.memo,
|
155
|
+
};
|
156
|
+
if (unsignedTx.memo && unsignedTx.memo !== ' ') {
|
157
|
+
signPayload.opReturnData = unsignedTx.memo;
|
158
|
+
}
|
159
|
+
|
160
|
+
const responseSign = await this.keepKeySdk.utxo.utxoSignTransaction(signPayload);
|
161
|
+
signedTx = responseSign.serializedTx;
|
162
|
+
break;
|
163
|
+
}
|
164
|
+
case 'TENDERMINT': {
|
165
|
+
switch (caip) {
|
166
|
+
case 'cosmos:cosmoshub-4/slip44:118': {
|
167
|
+
const msgType = unsignedTx.signDoc.msgs[0].type;
|
168
|
+
if (msgType === 'cosmos-sdk/MsgSend') {
|
169
|
+
const responseSign = await this.keepKeySdk.cosmos.cosmosSignAmino(unsignedTx);
|
170
|
+
signedTx = responseSign.serialized;
|
171
|
+
} else if (msgType === 'cosmos-sdk/MsgDelegate') {
|
172
|
+
const responseSign =
|
173
|
+
await this.keepKeySdk.cosmos.cosmosSignAminoDelegate(unsignedTx);
|
174
|
+
signedTx = responseSign.serialized;
|
175
|
+
} else if (msgType === 'cosmos-sdk/MsgUndelegate') {
|
176
|
+
const responseSign =
|
177
|
+
await this.keepKeySdk.cosmos.cosmosSignAminoUndelegate(unsignedTx);
|
178
|
+
signedTx = responseSign.serialized;
|
179
|
+
} else if (msgType === 'cosmos-sdk/MsgBeginRedelegate') {
|
180
|
+
const responseSign =
|
181
|
+
await this.keepKeySdk.cosmos.cosmosSignAminoRedelegate(unsignedTx);
|
182
|
+
signedTx = responseSign.serialized;
|
183
|
+
} else if (msgType === 'cosmos-sdk/MsgWithdrawDelegationReward') {
|
184
|
+
const responseSign =
|
185
|
+
await this.keepKeySdk.cosmos.cosmosSignAminoWithdrawDelegatorRewardsAll(
|
186
|
+
unsignedTx,
|
187
|
+
);
|
188
|
+
signedTx = responseSign.serialized;
|
189
|
+
} else {
|
190
|
+
throw new Error(`Unsupported CosmosHub message type: ${msgType}`);
|
191
|
+
}
|
192
|
+
break;
|
193
|
+
}
|
194
|
+
case 'cosmos:osmosis-1/slip44:118': {
|
195
|
+
const msgType = unsignedTx.signDoc.msgs[0].type;
|
196
|
+
if (msgType === 'cosmos-sdk/MsgSend') {
|
197
|
+
const responseSign = await this.keepKeySdk.osmosis.osmosisSignAmino(unsignedTx);
|
198
|
+
signedTx = responseSign.serialized;
|
199
|
+
} else if (msgType === 'cosmos-sdk/MsgDelegate') {
|
200
|
+
const responseSign =
|
201
|
+
await this.keepKeySdk.osmosis.osmoSignAminoDelegate(unsignedTx);
|
202
|
+
signedTx = responseSign.serialized;
|
203
|
+
} else if (msgType === 'cosmos-sdk/MsgUndelegate') {
|
204
|
+
const responseSign =
|
205
|
+
await this.keepKeySdk.osmosis.osmoSignAminoUndelegate(unsignedTx);
|
206
|
+
signedTx = responseSign.serialized;
|
207
|
+
} else if (msgType === 'cosmos-sdk/MsgBeginRedelegate') {
|
208
|
+
const responseSign =
|
209
|
+
await this.keepKeySdk.osmosis.osmoSignAminoRedelegate(unsignedTx);
|
210
|
+
signedTx = responseSign.serialized;
|
211
|
+
} else if (msgType === 'cosmos-sdk/MsgWithdrawDelegationReward') {
|
212
|
+
const responseSign =
|
213
|
+
await this.keepKeySdk.osmosis.osmoSignAminoWithdrawDelegatorRewardsAll(
|
214
|
+
unsignedTx,
|
215
|
+
);
|
216
|
+
signedTx = responseSign.serialized;
|
217
|
+
} else {
|
218
|
+
throw new Error(`Unsupported Osmosis message type: ${msgType}`);
|
219
|
+
}
|
220
|
+
break;
|
221
|
+
}
|
222
|
+
case 'cosmos:thorchain-mainnet-v1/slip44:931': {
|
223
|
+
if (unsignedTx.signDoc.msgs[0].type === 'thorchain/MsgSend') {
|
224
|
+
const responseSign =
|
225
|
+
await this.keepKeySdk.thorchain.thorchainSignAminoTransfer(unsignedTx);
|
226
|
+
signedTx = responseSign.serialized;
|
227
|
+
} else if (unsignedTx.signDoc.msgs[0].type === 'thorchain/MsgDeposit') {
|
228
|
+
const responseSign =
|
229
|
+
await this.keepKeySdk.thorchain.thorchainSignAminoDeposit(unsignedTx);
|
230
|
+
signedTx = responseSign.serialized;
|
231
|
+
} else {
|
232
|
+
throw new Error(
|
233
|
+
`Unsupported Thorchain message type: ${unsignedTx.signDoc.msgs[0].type}`,
|
234
|
+
);
|
235
|
+
}
|
236
|
+
break;
|
237
|
+
}
|
238
|
+
case 'cosmos:mayachain-mainnet-v1/slip44:931':
|
239
|
+
case 'cosmos:mayachain-mainnet-v1/denom:maya': {
|
240
|
+
if (unsignedTx.signDoc.msgs[0].type === 'mayachain/MsgSend') {
|
241
|
+
const responseSign =
|
242
|
+
await this.keepKeySdk.mayachain.mayachainSignAminoTransfer(unsignedTx);
|
243
|
+
signedTx = responseSign.serialized;
|
244
|
+
} else if (unsignedTx.signDoc.msgs[0].type === 'mayachain/MsgDeposit') {
|
245
|
+
const responseSign =
|
246
|
+
await this.keepKeySdk.mayachain.mayachainSignAminoDeposit(unsignedTx);
|
247
|
+
signedTx = responseSign.serialized;
|
248
|
+
} else {
|
249
|
+
throw new Error(
|
250
|
+
`Unsupported mayachain message type: ${unsignedTx.signDoc.msgs[0].type}`,
|
251
|
+
);
|
252
|
+
}
|
253
|
+
break;
|
254
|
+
}
|
255
|
+
default: {
|
256
|
+
throw new Error(`Unsupported Tendermint CAIP: ${caip}`);
|
257
|
+
}
|
258
|
+
}
|
259
|
+
break;
|
260
|
+
}
|
261
|
+
case 'EIP155': {
|
262
|
+
|
263
|
+
const responseSign = await this.keepKeySdk.eth.ethSignTransaction(unsignedTx);
|
264
|
+
if (responseSign?.serialized) {
|
265
|
+
const serialized = responseSign.serialized;
|
266
|
+
if (serialized.length > 140) {
|
267
|
+
signedTx = serialized;
|
268
|
+
} else {
|
269
|
+
console.error(
|
270
|
+
tag,
|
271
|
+
'EIP155 signing returned incomplete transaction - only signature components',
|
272
|
+
);
|
273
|
+
throw new Error(
|
274
|
+
'KeepKey returned incomplete transaction - cannot reconstruct without r,s,v components',
|
275
|
+
);
|
276
|
+
}
|
277
|
+
} else {
|
278
|
+
console.error(
|
279
|
+
tag,
|
280
|
+
'EIP155 signing failed - no valid signature in response:',
|
281
|
+
responseSign,
|
282
|
+
);
|
283
|
+
throw new Error('Failed to sign transaction - no valid signature in response');
|
284
|
+
}
|
285
|
+
break;
|
286
|
+
}
|
287
|
+
case 'OTHER': {
|
288
|
+
if (caip === 'ripple:4109c6f2045fc7eff4cde8f9905d19c2/slip44:144') {
|
289
|
+
let responseSign = await this.keepKeySdk.xrp.xrpSignTransaction(unsignedTx);
|
290
|
+
if (typeof responseSign === 'string') responseSign = JSON.parse(responseSign);
|
291
|
+
signedTx = responseSign.value.signatures[0].serializedTx;
|
292
|
+
} else {
|
293
|
+
throw new Error(`Unsupported OTHER CAIP: ${caip}`);
|
294
|
+
}
|
295
|
+
break;
|
296
|
+
}
|
297
|
+
default: {
|
298
|
+
throw new Error(`Unsupported CAIP: ${caip}`);
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
if (!signedTx) {
|
303
|
+
console.error(tag, 'CRITICAL ERROR: signedTx is missing after signing process');
|
304
|
+
console.error(tag, 'CAIP:', caip);
|
305
|
+
console.error(tag, 'Type:', type);
|
306
|
+
throw Error('Failed to sign! missing signedTx');
|
307
|
+
}
|
308
|
+
return signedTx;
|
309
|
+
} catch (e: any) {
|
310
|
+
console.error(tag, e);
|
311
|
+
throw e;
|
312
|
+
}
|
313
|
+
}
|
314
|
+
|
315
|
+
async broadcast({ networkId, serialized }: any): Promise<any> {
|
316
|
+
let tag = TAG + ' | broadcast | ';
|
317
|
+
try {
|
318
|
+
if (!this.pioneer) throw Error('Failed to init! pioneer');
|
319
|
+
if (!serialized) throw Error('Failed to broadcast! missing serialized2');
|
320
|
+
let result = await this.pioneer.Broadcast({ networkId, serialized });
|
321
|
+
result = result.data;
|
322
|
+
if (result.error) {
|
323
|
+
// Throw an error instead of returning the error object
|
324
|
+
throw new Error(`Broadcast failed: ${result.error}`);
|
325
|
+
} else {
|
326
|
+
return result.txid;
|
327
|
+
}
|
328
|
+
} catch (e: any) {
|
329
|
+
console.error(tag, e);
|
330
|
+
throw e;
|
331
|
+
}
|
332
|
+
}
|
333
|
+
}
|
@@ -0,0 +1,171 @@
|
|
1
|
+
import { ChartBalance, ChartParams, StakingPosition } from './types';
|
2
|
+
import { hydrateAssetData, checkDuplicateBalance, createBalanceIdentifier } from './utils';
|
3
|
+
|
4
|
+
const tag = '| charts-cosmos-staking |';
|
5
|
+
|
6
|
+
export async function getCosmosStakingCharts(params: ChartParams): Promise<ChartBalance[]> {
|
7
|
+
const { blockchains, pioneer, pubkeys, context } = params;
|
8
|
+
const balances: ChartBalance[] = [];
|
9
|
+
|
10
|
+
try {
|
11
|
+
console.log(tag, 'Adding Cosmos staking positions to charts...');
|
12
|
+
|
13
|
+
// Find cosmos pubkeys that could have staking positions
|
14
|
+
const cosmosPubkeys = pubkeys.filter(
|
15
|
+
(p: any) =>
|
16
|
+
p.networks &&
|
17
|
+
Array.isArray(p.networks) &&
|
18
|
+
p.networks.some(
|
19
|
+
(n: string) => n.includes('cosmos:cosmoshub') || n.includes('cosmos:osmosis'),
|
20
|
+
),
|
21
|
+
);
|
22
|
+
|
23
|
+
if (cosmosPubkeys.length === 0) {
|
24
|
+
console.log(tag, 'No cosmos pubkeys found for staking positions');
|
25
|
+
return balances;
|
26
|
+
}
|
27
|
+
|
28
|
+
console.log(tag, 'Found cosmos pubkeys for staking:', cosmosPubkeys.length);
|
29
|
+
|
30
|
+
for (const cosmosPubkey of cosmosPubkeys) {
|
31
|
+
if (!cosmosPubkey.address) {
|
32
|
+
continue;
|
33
|
+
}
|
34
|
+
|
35
|
+
// Check which cosmos networks this pubkey supports
|
36
|
+
const cosmosNetworks = cosmosPubkey.networks.filter(
|
37
|
+
(n: string) => n.includes('cosmos:cosmoshub') || n.includes('cosmos:osmosis'),
|
38
|
+
);
|
39
|
+
|
40
|
+
for (const networkId of cosmosNetworks) {
|
41
|
+
// Only process if this network is in our blockchains list
|
42
|
+
if (!blockchains.includes(networkId)) {
|
43
|
+
continue;
|
44
|
+
}
|
45
|
+
|
46
|
+
await fetchStakingPositionsForNetwork(
|
47
|
+
networkId,
|
48
|
+
cosmosPubkey.address,
|
49
|
+
context,
|
50
|
+
pioneer,
|
51
|
+
balances
|
52
|
+
);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
} catch (e) {
|
56
|
+
console.error(tag, 'Error adding cosmos staking positions:', e);
|
57
|
+
}
|
58
|
+
|
59
|
+
return balances;
|
60
|
+
}
|
61
|
+
|
62
|
+
async function fetchStakingPositionsForNetwork(
|
63
|
+
networkId: string,
|
64
|
+
address: string,
|
65
|
+
context: string,
|
66
|
+
pioneer: any,
|
67
|
+
balances: ChartBalance[]
|
68
|
+
): Promise<void> {
|
69
|
+
try {
|
70
|
+
console.log(tag, `Fetching staking positions for ${address} on ${networkId}...`);
|
71
|
+
|
72
|
+
// Convert networkId to network name for API
|
73
|
+
let network: string;
|
74
|
+
if (networkId === 'cosmos:cosmoshub-4') {
|
75
|
+
network = 'cosmos';
|
76
|
+
} else if (networkId === 'cosmos:osmosis-1') {
|
77
|
+
network = 'osmosis';
|
78
|
+
} else {
|
79
|
+
console.error(tag, `Unsupported networkId for staking: ${networkId}`);
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
|
83
|
+
// Get staking positions from pioneer server
|
84
|
+
const stakingResponse = await pioneer.GetStakingPositions({
|
85
|
+
network,
|
86
|
+
address,
|
87
|
+
});
|
88
|
+
|
89
|
+
if (!stakingResponse?.data || !Array.isArray(stakingResponse.data)) {
|
90
|
+
console.log(tag, `No staking positions found for ${address} on ${networkId}`);
|
91
|
+
return;
|
92
|
+
}
|
93
|
+
|
94
|
+
console.log(
|
95
|
+
tag,
|
96
|
+
`Found ${stakingResponse.data.length} staking positions for ${networkId}`,
|
97
|
+
);
|
98
|
+
|
99
|
+
for (const position of stakingResponse.data) {
|
100
|
+
const processedPosition = processStakingPosition(
|
101
|
+
position,
|
102
|
+
address,
|
103
|
+
context,
|
104
|
+
networkId
|
105
|
+
);
|
106
|
+
|
107
|
+
if (processedPosition && !checkDuplicateBalance(
|
108
|
+
balances,
|
109
|
+
processedPosition.caip,
|
110
|
+
processedPosition.pubkey,
|
111
|
+
processedPosition.validator
|
112
|
+
)) {
|
113
|
+
balances.push(processedPosition);
|
114
|
+
console.log(tag, `Added ${position.type} position:`, {
|
115
|
+
balance: processedPosition.balance,
|
116
|
+
ticker: processedPosition.ticker,
|
117
|
+
valueUsd: processedPosition.valueUsd,
|
118
|
+
validator: processedPosition.validator,
|
119
|
+
});
|
120
|
+
}
|
121
|
+
}
|
122
|
+
} catch (stakingError) {
|
123
|
+
console.error(
|
124
|
+
tag,
|
125
|
+
`Error fetching staking positions for ${address} on ${networkId}:`,
|
126
|
+
stakingError,
|
127
|
+
);
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
function processStakingPosition(
|
132
|
+
position: StakingPosition,
|
133
|
+
address: string,
|
134
|
+
context: string,
|
135
|
+
networkId: string
|
136
|
+
): ChartBalance | null {
|
137
|
+
// Validate position has required fields
|
138
|
+
if (!position.balance || position.balance <= 0 || !position.caip) {
|
139
|
+
return null;
|
140
|
+
}
|
141
|
+
|
142
|
+
// Hydrate staking position with assetData
|
143
|
+
const stakingAssetInfo = hydrateAssetData(position.caip);
|
144
|
+
|
145
|
+
// Staking positions are not tokens, they represent staked native assets
|
146
|
+
const stakingBalance: ChartBalance = {
|
147
|
+
context,
|
148
|
+
chart: 'staking',
|
149
|
+
contextType: context.split(':')[0],
|
150
|
+
name: stakingAssetInfo?.name || position.name || `${position.type} Position`,
|
151
|
+
caip: position.caip,
|
152
|
+
icon: stakingAssetInfo?.icon || position.icon || '',
|
153
|
+
pubkey: address,
|
154
|
+
ticker: stakingAssetInfo?.symbol || position.ticker || position.symbol || 'UNK',
|
155
|
+
ref: `${context}${position.caip}`,
|
156
|
+
identifier: createBalanceIdentifier(position.caip, address),
|
157
|
+
networkId,
|
158
|
+
symbol: stakingAssetInfo?.symbol || position.symbol || position.ticker || 'UNK',
|
159
|
+
type: stakingAssetInfo?.type || position.type || 'staking',
|
160
|
+
token: false, // Staking positions are not tokens
|
161
|
+
decimal: stakingAssetInfo?.decimal,
|
162
|
+
balance: position.balance.toString(),
|
163
|
+
priceUsd: position.priceUsd || 0,
|
164
|
+
valueUsd: position.valueUsd || position.balance * (position.priceUsd || 0),
|
165
|
+
status: position.status || 'active',
|
166
|
+
validator: position.validatorAddress || position.validator || '',
|
167
|
+
updated: new Date().getTime(),
|
168
|
+
};
|
169
|
+
|
170
|
+
return stakingBalance;
|
171
|
+
}
|