Skip to content

Commit 352c6c3

Browse files
2 parents 631ede3 + 4c6a176 commit 352c6c3

File tree

74 files changed

+4997
-575
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

74 files changed

+4997
-575
lines changed

.github/workflows/ci.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,43 @@ jobs:
134134
if: matrix.check == 'audit'
135135
run: yarn run improved-yarn-audit --min-severity high
136136

137+
license-analysis:
138+
runs-on: ubuntu-latest
139+
140+
steps:
141+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
142+
143+
- name: Setup node 22
144+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
145+
with:
146+
node-version: 22
147+
148+
- name: restore lerna dependencies
149+
id: lerna-cache
150+
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 #v4.2.3
151+
with:
152+
path: |
153+
node_modules
154+
modules/*/node_modules
155+
key: ${{ runner.os }}-node22-${{ hashFiles('yarn.lock') }}-${{ hashFiles('tsconfig.packages.json') }}-${{ hashFiles('package.json') }}
156+
157+
- name: Install Packages
158+
if: steps.lerna-cache.outputs.cache-hit != 'true'
159+
run: yarn install --with-frozen-lockfile --ignore-scripts
160+
161+
- name: build packages
162+
env:
163+
# Workaround for https://github.com/nodejs/node/issues/51555
164+
DISABLE_V8_COMPILE_CACHE: '1'
165+
run: yarn run postinstall
166+
167+
- name: Run Fossa Analysis
168+
uses: fossas/fossa-action@3ebcea1862c6ffbd5cf1b4d0bd6b3fe7bd6f2cac # v1.7.0
169+
with:
170+
api-key: ${{ secrets.FOSSA_API_KEY }}
171+
branch: ${{ github.head_ref || github.ref_name }}
172+
project: BitGo/BitGoJS
173+
137174
browser-test:
138175
runs-on: ubuntu-22.04
139176

modules/abstract-eth/src/lib/transactionBuilder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
248248
case TransactionType.FlushERC721:
249249
this.setContract(transactionJson.to);
250250
const erc721Data = decodeFlushERC721TokensData(transactionJson.data, transactionJson.to);
251-
if (erc721Data.forwarderVersion >= 4) {
251+
if (erc721Data.forwarderVersion === 4) {
252252
this.forwarderVersion(erc721Data.forwarderVersion);
253253
}
254254
this.forwarderAddress(erc721Data.forwarderAddress);
@@ -258,7 +258,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
258258
case TransactionType.FlushERC1155:
259259
this.setContract(transactionJson.to);
260260
const erc1155Data = decodeFlushERC1155TokensData(transactionJson.data, transactionJson.to);
261-
if (erc1155Data.forwarderVersion >= 4) {
261+
if (erc1155Data.forwarderVersion === 4) {
262262
this.forwarderVersion(erc1155Data.forwarderVersion);
263263
}
264264
this.forwarderAddress(erc1155Data.forwarderAddress);

modules/abstract-eth/src/lib/utils.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ export function decodeFlushERC721TokensData(
259259
forwarderAddress: string;
260260
tokenAddress: string;
261261
tokenId: string;
262-
forwarderVersion: number;
262+
forwarderVersion?: number;
263263
} {
264264
if (data.startsWith(flushERC721ForwarderTokensMethodIdV4)) {
265265
if (!to) {
@@ -284,7 +284,6 @@ export function decodeFlushERC721TokensData(
284284
forwarderAddress: addHexPrefix(forwarderAddress as string),
285285
tokenAddress: addHexPrefix(tokenAddress as string),
286286
tokenId: new BigNumber(bufferToHex(tokenId as Buffer)).toFixed(),
287-
forwarderVersion: 0,
288287
};
289288
}
290289
throw new BuildTransactionError(`Invalid flush ERC721 bytecode: ${data}`);
@@ -332,7 +331,7 @@ export function decodeFlushERC1155TokensData(
332331
forwarderAddress: string;
333332
tokenAddress: string;
334333
tokenId: string;
335-
forwarderVersion: number;
334+
forwarderVersion?: number;
336335
} {
337336
if (data.startsWith(flushERC1155ForwarderTokensMethodIdV4)) {
338337
if (!to) {
@@ -357,7 +356,6 @@ export function decodeFlushERC1155TokensData(
357356
forwarderAddress: addHexPrefix(forwarderAddress as string),
358357
tokenAddress: addHexPrefix(tokenAddress as string),
359358
tokenId: new BigNumber(bufferToHex(tokenId as Buffer)).toFixed(),
360-
forwarderVersion: 0,
361359
};
362360
}
363361
throw new BuildTransactionError(`Invalid flush ERC1155 bytecode: ${data}`);

modules/abstract-eth/test/unit/utils.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ describe('Abstract ETH Utils', () => {
3939
const forwarderAddress = '0x8f977e912ef500548a0c3be6ddde9899f1199b81';
4040
const tokenAddress = '0xdf7decb1baa8f529f0c8982cbb4be50357195299';
4141
const tokenId = '12345';
42-
const forwarderVersion = 0;
42+
const forwarderVersion = 2;
4343

4444
const encoded = flushERC721TokensData(forwarderAddress, tokenAddress, tokenId, forwarderVersion);
4545
const decoded = decodeFlushERC721TokensData(encoded);
@@ -48,7 +48,7 @@ describe('Abstract ETH Utils', () => {
4848
decoded.forwarderAddress.toLowerCase().should.equal(forwarderAddress.toLowerCase());
4949
decoded.tokenAddress.toLowerCase().should.equal(tokenAddress.toLowerCase());
5050
decoded.tokenId.should.equal(tokenId);
51-
decoded.forwarderVersion.should.equal(0);
51+
should.not.exist(decoded.forwarderVersion);
5252
});
5353

5454
it('should decode flush ERC721 data correctly for v4+', () => {
@@ -64,7 +64,8 @@ describe('Abstract ETH Utils', () => {
6464
decoded.forwarderAddress.toLowerCase().should.equal(forwarderAddress.toLowerCase());
6565
decoded.tokenAddress.toLowerCase().should.equal(tokenAddress.toLowerCase());
6666
decoded.tokenId.should.equal(tokenId);
67-
decoded.forwarderVersion.should.equal(4);
67+
should.exist(decoded.forwarderVersion);
68+
should.equal(decoded.forwarderVersion, 4);
6869
});
6970

7071
it('should handle large token IDs for ERC721', () => {
@@ -133,7 +134,7 @@ describe('Abstract ETH Utils', () => {
133134
const forwarderAddress = '0x8f977e912ef500548a0c3be6ddde9899f1199b81';
134135
const tokenAddress = '0xdf7decb1baa8f529f0c8982cbb4be50357195299';
135136
const tokenId = '99999';
136-
const forwarderVersion = 0;
137+
const forwarderVersion = 2;
137138

138139
const encoded = flushERC1155TokensData(forwarderAddress, tokenAddress, tokenId, forwarderVersion);
139140
const decoded = decodeFlushERC1155TokensData(encoded);
@@ -142,7 +143,7 @@ describe('Abstract ETH Utils', () => {
142143
decoded.forwarderAddress.toLowerCase().should.equal(forwarderAddress.toLowerCase());
143144
decoded.tokenAddress.toLowerCase().should.equal(tokenAddress.toLowerCase());
144145
decoded.tokenId.should.equal(tokenId);
145-
decoded.forwarderVersion.should.equal(0);
146+
should.not.exist(decoded.forwarderVersion);
146147
});
147148

148149
it('should decode flush ERC1155 data correctly for v4+', () => {
@@ -158,7 +159,8 @@ describe('Abstract ETH Utils', () => {
158159
decoded.forwarderAddress.toLowerCase().should.equal(forwarderAddress.toLowerCase());
159160
decoded.tokenAddress.toLowerCase().should.equal(tokenAddress.toLowerCase());
160161
decoded.tokenId.should.equal(tokenId);
161-
decoded.forwarderVersion.should.equal(4);
162+
should.exist(decoded.forwarderVersion);
163+
should.equal(decoded.forwarderVersion, 4);
162164
});
163165

164166
it('should handle token ID 0 for ERC1155', () => {

modules/abstract-substrate/src/lib/iface.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ export const MethodNames = {
7979
* Transfer stake from one validator to another.
8080
*/
8181
TransferStake: 'transferStake' as const,
82+
/**
83+
* Move stake from one hotkey to another.
84+
*/
85+
MoveStake: 'moveStake' as const,
8286
} as const;
8387

8488
/**
@@ -195,6 +199,14 @@ export interface TransferStakeArgs extends Args {
195199
alphaAmount: string;
196200
}
197201

202+
export interface MoveStakeArgs extends Args {
203+
originHotkey: string;
204+
destinationHotkey: string;
205+
originNetuid: string;
206+
destinationNetuid: string;
207+
alphaAmount: string;
208+
}
209+
198210
/**
199211
* Decoded TxMethod from a transaction hex
200212
*/
@@ -211,7 +223,8 @@ export interface TxMethod {
211223
| UnbondArgs
212224
| WithdrawUnbondedArgs
213225
| BatchArgs
214-
| TransferStakeArgs;
226+
| TransferStakeArgs
227+
| MoveStakeArgs;
215228
name: MethodNamesValues;
216229
pallet: string;
217230
}

modules/abstract-substrate/src/lib/txnSchema.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,11 @@ export const TransferStakeTransactionSchema = joi.object({
6565
destinationNetuid: joi.string().required(),
6666
alphaAmount: joi.string().required(),
6767
});
68+
69+
export const MoveStakeTransactionSchema = joi.object({
70+
originHotkey: addressSchema.required(),
71+
destinationHotkey: addressSchema.required(),
72+
originNetuid: joi.string().required(),
73+
destinationNetuid: joi.string().required(),
74+
alphaAmount: joi.string().required(),
75+
});

modules/abstract-substrate/src/lib/utils.ts

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { hexToU8a, isHex, u8aToHex, u8aToU8a } from '@polkadot/util';
88
import { base64Decode, signatureVerify } from '@polkadot/util-crypto';
99
import { UnsignedTransaction } from '@substrate/txwrapper-core';
1010
import { DecodedSignedTx, DecodedSigningPayload, TypeRegistry } from '@substrate/txwrapper-core/lib/types';
11-
import { construct } from '@substrate/txwrapper-polkadot';
11+
import { construct, decode } from '@substrate/txwrapper-polkadot';
1212
import bs58 from 'bs58';
1313
import base32 from 'hi-base32';
1414
import nacl from 'tweetnacl';
@@ -28,7 +28,9 @@ import {
2828
UnbondArgs,
2929
WithdrawUnbondedArgs,
3030
BatchArgs,
31+
MoveStakeArgs,
3132
} from './iface';
33+
import { SingletonRegistry } from './singletonRegistry';
3234

3335
export class Utils implements BaseUtils {
3436
/** @inheritdoc */
@@ -263,6 +265,16 @@ export class Utils implements BaseUtils {
263265
return (arg as BatchArgs).calls !== undefined && Array.isArray((arg as BatchArgs).calls);
264266
}
265267

268+
isMoveStake(arg: TxMethod['args']): arg is MoveStakeArgs {
269+
return (
270+
(arg as MoveStakeArgs).originHotkey !== undefined &&
271+
(arg as MoveStakeArgs).destinationHotkey !== undefined &&
272+
(arg as MoveStakeArgs).originNetuid !== undefined &&
273+
(arg as MoveStakeArgs).destinationNetuid !== undefined &&
274+
(arg as MoveStakeArgs).alphaAmount !== undefined
275+
);
276+
}
277+
266278
/**
267279
* extracts and returns the signature in hex format given a raw signed transaction
268280
*
@@ -306,6 +318,31 @@ export class Utils implements BaseUtils {
306318
getMaterial(networkType: NetworkType): Material {
307319
throw new Error('Method not implemented.');
308320
}
321+
322+
/**
323+
* Decodes a substrate transaction from raw transaction hex
324+
*
325+
* @param {string} txHex - The raw transaction hex string to decode (signed or unsigned)
326+
* @param {Material} material - Network material containing metadata and chain information
327+
* @param {boolean} [isImmortalEra] - Whether the transaction uses immortal era (optional)
328+
* @returns {DecodedSignedTx | DecodedSigningPayload} The decoded transaction object
329+
*/
330+
decodeTransaction(txHex: string, material: Material, isImmortalEra = false): DecodedSignedTx | DecodedSigningPayload {
331+
try {
332+
const registry = SingletonRegistry.getInstance(material);
333+
334+
// Attempt to decode as a signed transaction or unsigned transaction
335+
const decoded = decode(txHex, {
336+
metadataRpc: material.metadata,
337+
registry,
338+
isImmortalEra,
339+
});
340+
341+
return decoded;
342+
} catch (error) {
343+
throw new Error(`Failed to decode transaction: ${error}`);
344+
}
345+
}
309346
}
310347

311348
const utils = new Utils();

modules/bitgo/src/v2/coinFactory.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import {
3737
VetTokenConfig,
3838
TaoTokenConfig,
3939
PolyxTokenConfig,
40+
JettonTokenConfig,
4041
} from '@bitgo/statics';
4142
import {
4243
Ada,
@@ -99,6 +100,7 @@ import {
99100
Injective,
100101
Iota,
101102
Islm,
103+
JettonToken,
102104
Lnbtc,
103105
Ltc,
104106
Mon,
@@ -528,6 +530,10 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin
528530
({ name, coinConstructor }) => coinFactory.register(name, coinConstructor)
529531
);
530532

533+
JettonToken.createTokenConstructors([...tokens.bitcoin.ton.tokens, ...tokens.testnet.ton.tokens]).forEach(
534+
({ name, coinConstructor }) => coinFactory.register(name, coinConstructor)
535+
);
536+
531537
VetToken.createTokenConstructors().forEach(({ name, coinConstructor }) =>
532538
coinFactory.register(name, coinConstructor)
533539
);
@@ -971,6 +977,9 @@ export function getTokenConstructor(tokenConfig: TokenConfig): CoinConstructor |
971977
case 'flr':
972978
case 'tflr':
973979
return FlrToken.createTokenConstructor(tokenConfig as EthLikeTokenConfig);
980+
case 'ton':
981+
case 'tton':
982+
return JettonToken.createTokenConstructor(tokenConfig as JettonTokenConfig);
974983
default:
975984
return undefined;
976985
}

modules/bitgo/src/v2/coins/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ import { Stx, Tstx, Sip10Token } from '@bitgo/sdk-coin-stx';
6060
import { Sui, Tsui, SuiToken } from '@bitgo/sdk-coin-sui';
6161
import { Tao, Ttao, TaoToken } from '@bitgo/sdk-coin-tao';
6262
import { Tia, Ttia } from '@bitgo/sdk-coin-tia';
63-
import { Ton, Tton } from '@bitgo/sdk-coin-ton';
63+
import { Ton, Tton, JettonToken } from '@bitgo/sdk-coin-ton';
6464
import { Trx, Ttrx } from '@bitgo/sdk-coin-trx';
6565
import { StellarToken, Txlm, Xlm } from '@bitgo/sdk-coin-xlm';
6666
import { Vet, Tvet, VetToken } from '@bitgo/sdk-coin-vet';
@@ -131,7 +131,7 @@ export { Stx, Tstx, Sip10Token };
131131
export { Sui, Tsui, SuiToken };
132132
export { Tao, Ttao, TaoToken };
133133
export { Tia, Ttia };
134-
export { Ton, Tton };
134+
export { Ton, Tton, JettonToken };
135135
export { Bld, Tbld };
136136
export { Sei, Tsei };
137137
export { Injective, Tinjective };

modules/bitgo/test/browser/browser.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ describe('Coins', () => {
5757
EthLikeErc20Token: 1,
5858
HashToken: 1,
5959
FlrToken: 1,
60+
JettonToken: 1,
6061
};
6162
Object.keys(BitGoJS.Coin)
6263
.filter((coinName) => !excludedKeys[coinName])

0 commit comments

Comments
 (0)