diff --git a/modules/abstract-cosmos/package.json b/modules/abstract-cosmos/package.json index e3f7fd5f19..3135a2c7d7 100644 --- a/modules/abstract-cosmos/package.json +++ b/modules/abstract-cosmos/package.json @@ -49,7 +49,7 @@ "@cosmjs/stargate": "^0.29.5", "bignumber.js": "^9.1.1", "cosmjs-types": "^0.6.1", - "lodash": "^4.18.0", + "lodash": "^4.17.21", "protobufjs": "^7.4.0", "superagent": "^9.0.1" }, diff --git a/modules/abstract-eth/package.json b/modules/abstract-eth/package.json index 445f9a1cc9..5e5754e250 100644 --- a/modules/abstract-eth/package.json +++ b/modules/abstract-eth/package.json @@ -55,7 +55,7 @@ "ethereumjs-util": "7.1.5", "ethers": "^5.1.3", "keccak": "^3.0.3", - "lodash": "^4.18.0", + "lodash": "4.17.21", "secp256k1": "5.0.1", "superagent": "^9.0.1" }, diff --git a/modules/abstract-substrate/package.json b/modules/abstract-substrate/package.json index 13cdf99937..2f9a0f6549 100644 --- a/modules/abstract-substrate/package.json +++ b/modules/abstract-substrate/package.json @@ -53,7 +53,7 @@ "bs58": "^4.0.1", "hi-base32": "^0.5.1", "joi": "^17.4.0", - "lodash": "^4.18.0", + "lodash": "^4.17.15", "tweetnacl": "^1.0.3" }, "gitHead": "18e460ddf02de2dbf13c2aa243478188fb539f0c", diff --git a/modules/abstract-utxo/package.json b/modules/abstract-utxo/package.json index ca98a7513c..b4e8fa30a0 100644 --- a/modules/abstract-utxo/package.json +++ b/modules/abstract-utxo/package.json @@ -72,7 +72,7 @@ "bignumber.js": "^9.0.2", "debug": "^3.1.0", "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "superagent": "^9.0.1" }, "devDependencies": { diff --git a/modules/bitgo/package.json b/modules/bitgo/package.json index 90b60a2da3..3a919827e1 100644 --- a/modules/bitgo/package.json +++ b/modules/bitgo/package.json @@ -132,7 +132,7 @@ "@bitgo/utxo-lib": "^11.22.0", "@types/superagent": "^4.1.3", "bignumber.js": "^9.1.1", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "openpgp": "5.11.3", "stellar-sdk": "^10.0.1", "superagent": "^9.0.1" diff --git a/modules/bitgo/test/v2/unit/keychains.ts b/modules/bitgo/test/v2/unit/keychains.ts index fa70e4ffc3..024d8f08c4 100644 --- a/modules/bitgo/test/v2/unit/keychains.ts +++ b/modules/bitgo/test/v2/unit/keychains.ts @@ -115,6 +115,7 @@ describe('V2 Keychains', function () { n.asset !== UnderlyingAsset.ARCUSDC && n.asset !== UnderlyingAsset.ZKSYNCERA && n.asset !== UnderlyingAsset.HYPERLIQUID && + n.asset !== UnderlyingAsset.BOBAETH && coinFamilyValues.includes(n.name) ); diff --git a/modules/express/package.json b/modules/express/package.json index a133cc2b75..f402d86f89 100644 --- a/modules/express/package.json +++ b/modules/express/package.json @@ -53,7 +53,7 @@ "express": "4.21.2", "io-ts": "npm:@bitgo-forks/io-ts@2.1.4", "io-ts-types": "^0.5.19", - "lodash": "^4.18.0", + "lodash": "^4.17.20", "morgan": "^1.9.1", "proxy-agent": "6.4.0", "proxyquire": "^2.1.3", diff --git a/modules/express/src/clientRoutes.ts b/modules/express/src/clientRoutes.ts index ff0c454456..cd74055800 100755 --- a/modules/express/src/clientRoutes.ts +++ b/modules/express/src/clientRoutes.ts @@ -625,7 +625,7 @@ export async function handleV2OFCSignPayload( const walletPassphrase = bodyWalletPassphrase || getWalletPwFromEnv(wallet.id()); const tradingAccount = wallet.toTradingAccount(); - const stringifiedPayload = typeof payload === 'string' ? payload : JSON.stringify(payload); + const stringifiedPayload = JSON.stringify(payload); const signature = await tradingAccount.signPayload({ payload: stringifiedPayload, walletPassphrase, @@ -1693,10 +1693,6 @@ export function setupAPIRoutes(app: express.Application, config: Config): void { router.post('express.decrypt', [prepareBitGo(config), typedPromiseWrapper(handleDecrypt)]); router.post('express.encrypt', [prepareBitGo(config), typedPromiseWrapper(handleEncrypt)]); router.post('express.verifyaddress', [prepareBitGo(config), typedPromiseWrapper(handleVerifyAddress)]); - router.post('express.v1.calculateminerfeeinfo', [ - prepareBitGo(config), - typedPromiseWrapper(handleCalculateMinerFeeInfo), - ]); router.post('express.calculateminerfeeinfo', [ prepareBitGo(config), typedPromiseWrapper(handleCalculateMinerFeeInfo), diff --git a/modules/express/src/typedRoutes/api/v1/calculateMinerFeeInfo.ts b/modules/express/src/typedRoutes/api/common/calculateMinerFeeInfo.ts similarity index 78% rename from modules/express/src/typedRoutes/api/v1/calculateMinerFeeInfo.ts rename to modules/express/src/typedRoutes/api/common/calculateMinerFeeInfo.ts index 549ecb992e..39f73e7c3f 100644 --- a/modules/express/src/typedRoutes/api/v1/calculateMinerFeeInfo.ts +++ b/modules/express/src/typedRoutes/api/common/calculateMinerFeeInfo.ts @@ -27,16 +27,22 @@ export const CalculateMinerFeeInfoResponse = t.type({ }); /** - * Calculate miner fee info (v1) + * Calculate miner fee info * * Calculates the estimated size and fee for a transaction based on the number and types of inputs and outputs. * This is useful for estimating the fee before creating a transaction. * - * @operationId express.v1.calculateminerfeeinfo + * The calculation takes into account: + * 1. The number and types of inputs (P2SH, P2PKH, P2SH-P2WSH) + * 2. The number of outputs + * 3. Whether the transaction contains uncompressed public keys + * 4. The fee rate (in satoshis per kilobyte) + * + * @operationId express.calculateminerfeeinfo * @tag express */ -export const PostV1CalculateMinerFeeInfo = httpRoute({ - path: '/api/v1/calculateminerfeeinfo', +export const PostCalculateMinerFeeInfo = httpRoute({ + path: '/api/v[12]/calculateminerfeeinfo', method: 'POST', request: httpRequest({ body: CalculateMinerFeeInfoRequestBody, diff --git a/modules/express/src/typedRoutes/api/index.ts b/modules/express/src/typedRoutes/api/index.ts index 24aed10b50..f16bb76e42 100644 --- a/modules/express/src/typedRoutes/api/index.ts +++ b/modules/express/src/typedRoutes/api/index.ts @@ -8,8 +8,7 @@ import { PostLogin } from './common/login'; import { PostDecrypt } from './common/decrypt'; import { PostEncrypt } from './common/encrypt'; import { PostVerifyAddress } from './common/verifyAddress'; -import { PostV1CalculateMinerFeeInfo } from './v1/calculateMinerFeeInfo'; -import { PostV2CalculateMinerFeeInfo } from './v2/calculateMinerFeeInfo'; +import { PostCalculateMinerFeeInfo } from './common/calculateMinerFeeInfo'; import { PostAcceptShare } from './v1/acceptShare'; import { PostSimpleCreate } from './v1/simpleCreate'; import { PutPendingApproval } from './v1/pendingApproval'; @@ -104,11 +103,8 @@ export const ExpressVerifyCoinAddressApiSpec = apiSpec({ }); export const ExpressCalculateMinerFeeInfoApiSpec = apiSpec({ - 'express.v1.calculateminerfeeinfo': { - post: PostV1CalculateMinerFeeInfo, - }, 'express.calculateminerfeeinfo': { - post: PostV2CalculateMinerFeeInfo, + post: PostCalculateMinerFeeInfo, }, }); diff --git a/modules/express/src/typedRoutes/api/v2/calculateMinerFeeInfo.ts b/modules/express/src/typedRoutes/api/v2/calculateMinerFeeInfo.ts deleted file mode 100644 index e2f906b7a6..0000000000 --- a/modules/express/src/typedRoutes/api/v2/calculateMinerFeeInfo.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { httpRoute, httpRequest } from '@api-ts/io-ts-http'; -import { BitgoExpressError } from '../../schemas/error'; -import { CalculateMinerFeeInfoRequestBody, CalculateMinerFeeInfoResponse } from '../v1/calculateMinerFeeInfo'; - -/** - * Calculate miner fee info - * - * Calculates the estimated size and fee for a transaction based on the number and types of inputs and outputs. - * This is useful for estimating the fee before creating a transaction. - * - * The calculation takes into account: - * 1. The number and types of inputs (P2SH, P2PKH, P2SH-P2WSH) - * 2. The number of outputs - * 3. Whether the transaction contains uncompressed public keys - * 4. The fee rate (in satoshis per kilobyte) - * - * @operationId express.calculateminerfeeinfo - * @tag express - */ -export const PostV2CalculateMinerFeeInfo = httpRoute({ - path: '/api/v2/calculateminerfeeinfo', - method: 'POST', - request: httpRequest({ - body: CalculateMinerFeeInfoRequestBody, - }), - response: { - 200: CalculateMinerFeeInfoResponse, - 400: BitgoExpressError, - 404: BitgoExpressError, - }, -}); diff --git a/modules/express/src/typedRoutes/api/v2/lightningState.ts b/modules/express/src/typedRoutes/api/v2/lightningState.ts index d4c69ffb7b..bea550427a 100644 --- a/modules/express/src/typedRoutes/api/v2/lightningState.ts +++ b/modules/express/src/typedRoutes/api/v2/lightningState.ts @@ -9,12 +9,11 @@ import { WalletState } from '../../../lightning/codecs'; export const LightningStateParams = { /** A lightning coin name (e.g., lnbtc or tlnbtc) */ coin: t.string, - /** The wallet ID. */ + /** The ID of the lightning self-custody wallet */ walletId: t.string, } as const; export const LightningStateResponse200 = t.type({ - /** NON_EXISTING LOCKED UNLOCKED RPC_ACTIVE SERVER_ACTIVE WAITING_TO_START */ state: WalletState, }); @@ -29,10 +28,12 @@ export const LightningStateResponse = { } as const; /** + * Lightning - Get node state + * * This is only used for self-custody lightning. Get the current state of the lightning node. * * @operationId express.lightning.getState - * @tag Express + * @tag express */ export const GetLightningState = httpRoute({ method: 'GET', diff --git a/modules/express/src/typedRoutes/api/v2/lightningWithdraw.ts b/modules/express/src/typedRoutes/api/v2/lightningWithdraw.ts index 4e88d77f5a..53ee4ead71 100644 --- a/modules/express/src/typedRoutes/api/v2/lightningWithdraw.ts +++ b/modules/express/src/typedRoutes/api/v2/lightningWithdraw.ts @@ -9,7 +9,7 @@ import { BitgoExpressError } from '../../schemas/error'; export const LightningWithdrawParams = { /** The coin identifier (e.g., 'lnbtc', 'tlnbtc') */ coin: t.string, - /** The wallet ID. */ + /** The ID of the wallet */ id: t.string, } as const; @@ -27,17 +27,17 @@ const LightningOnchainRecipient = t.type({ * Request body for lightning onchain withdrawal */ export const LightningWithdrawRequestBody = { - /** A list of on-chain recipients with their withdrawal amounts. */ + /** Array of recipients to pay */ recipients: t.array(LightningOnchainRecipient), - /** The wallet passphrase. */ + /** Wallet passphrase for signing */ passphrase: t.string, - /** Optional fee rate for the transaction in satoshis per virtual byte. Cannot be used with numBlocks. */ + /** Fee rate in satoshis per virtual byte (as string that will be converted to BigInt) */ satsPerVbyte: optional(BigIntFromString), - /** The number of blocks required to confirm a transaction. You can use numBlocks to estimate the fee rate by targeting confirmation within a given number of blocks. If both satsPerVbyte and numBlocks are absent, the transaction defaults to 2 blocks for confirmation. */ + /** Target number of blocks for confirmation */ numBlocks: optional(t.number), - /** Optional sequence ID for the withdrawal transfer. */ + /** Optional sequence ID for the withdraw transfer */ sequenceId: optional(t.string), - /** Optional comment for the withdrawal transfer. */ + /** Optional comment for the withdraw transfer */ comment: optional(t.string), } as const; @@ -174,7 +174,7 @@ const PendingApproval = t.intersection([ */ const LightningWithdrawResponse = t.intersection([ t.type({ - /** Transaction request identifier. */ + /** Unique identifier for withdraw request submitted to BitGo */ txRequestId: t.string, /** Status of withdraw request submission to BitGo */ txRequestState: TxRequestState, @@ -199,10 +199,12 @@ export const LightningWithdrawResponseType = { } as const; /** - * Withdraw onchain balance from a lightning wallet to a regular onchain address. + * Lightning Onchain Withdrawal API + * + * Withdraws lightning balance to an onchain Bitcoin address * * @operationId express.v2.wallet.lightningWithdraw - * @tag Express + * @tag express */ export const PostLightningWalletWithdraw = httpRoute({ path: '/api/v2/{coin}/wallet/{id}/lightning/withdraw', diff --git a/modules/express/src/typedRoutes/api/v2/ofcExtSignPayload.ts b/modules/express/src/typedRoutes/api/v2/ofcExtSignPayload.ts index 2dac9c2a66..148d9b008a 100644 --- a/modules/express/src/typedRoutes/api/v2/ofcExtSignPayload.ts +++ b/modules/express/src/typedRoutes/api/v2/ofcExtSignPayload.ts @@ -17,9 +17,14 @@ import { OfcSignPayloadBody, OfcSignPayloadResponse } from './ofcSignPayload'; * - Encrypted private keys must be available in the file system * - Wallet passphrase must be provided via request body or environment variable * + * **Flow**: + * 1. Reads encrypted private key from filesystem + * 2. Decrypts private key using wallet passphrase + * 3. Signs the payload with the decrypted key + * 4. Returns signed payload and hex-encoded signature * * @operationId express.v2.ofc.extSignPayload - * @tag Express + * @tag express */ export const PostOfcExtSignPayload = httpRoute({ path: '/api/v2/ofc/signPayload', diff --git a/modules/express/test/unit/clientRoutes/signPayload.ts b/modules/express/test/unit/clientRoutes/signPayload.ts index adcfee820e..b239ff537a 100644 --- a/modules/express/test/unit/clientRoutes/signPayload.ts +++ b/modules/express/test/unit/clientRoutes/signPayload.ts @@ -87,32 +87,6 @@ describe('Sign an arbitrary payload with trading account key', function () { throw new Error(`Response did not match expected codec`); }); }); - it('should not double-stringify when decoded payload is already a string', async function () { - // When the io-ts Json codec matches a string input (left-to-right union resolution), - // decoded.payload is the original string. The handler must not JSON.stringify it again. - const expectedResponse = { - payload: stringifiedPayload, - signature, - }; - const req = { - bitgo: bitGoStub, - body: { - payload: stringifiedPayload, - walletId, - }, - decoded: { - walletId, - payload: stringifiedPayload, - }, - query: {}, - } as unknown as ExpressApiRouteRequest<'express.ofc.signPayload', 'post'>; - const result = await handleV2OFCSignPayload(req).should.be.resolvedWith(expectedResponse); - result.payload.should.equal(stringifiedPayload); - result.payload.should.not.startWith('"'); - decodeOrElse('OfcSignPayloadResponse200', OfcSignPayloadResponse[200], result, (_) => { - throw new Error(`Response did not match expected codec`); - }); - }); it('should decode handler response with OfcSignPayloadResponse codec', async function () { const expected = { payload: JSON.stringify(payload), diff --git a/modules/express/test/unit/typedRoutes/calculateMinerFeeInfo.ts b/modules/express/test/unit/typedRoutes/calculateMinerFeeInfo.ts index cdc6562ffc..1d3f62e3b3 100644 --- a/modules/express/test/unit/typedRoutes/calculateMinerFeeInfo.ts +++ b/modules/express/test/unit/typedRoutes/calculateMinerFeeInfo.ts @@ -3,9 +3,8 @@ import * as t from 'io-ts'; import { CalculateMinerFeeInfoRequestBody, CalculateMinerFeeInfoResponse, - PostV1CalculateMinerFeeInfo, -} from '../../../src/typedRoutes/api/v1/calculateMinerFeeInfo'; -import { PostV2CalculateMinerFeeInfo } from '../../../src/typedRoutes/api/v2/calculateMinerFeeInfo'; + PostCalculateMinerFeeInfo, +} from '../../../src/typedRoutes/api/common/calculateMinerFeeInfo'; import { assertDecode } from './common'; import 'should'; import 'should-http'; @@ -302,43 +301,25 @@ describe('CalculateMinerFeeInfo codec tests', function () { }); }); - describe('PostV1CalculateMinerFeeInfo route definition', function () { - it('should have the correct path for v1', function () { - assert.strictEqual(PostV1CalculateMinerFeeInfo.path, '/api/v1/calculateminerfeeinfo'); + describe('PostCalculateMinerFeeInfo route definition', function () { + it('should have the correct path', function () { + assert.strictEqual(PostCalculateMinerFeeInfo.path, '/api/v[12]/calculateminerfeeinfo'); }); it('should have the correct HTTP method', function () { - assert.strictEqual(PostV1CalculateMinerFeeInfo.method, 'POST'); + assert.strictEqual(PostCalculateMinerFeeInfo.method, 'POST'); }); it('should have the correct request configuration', function () { - assert.ok(PostV1CalculateMinerFeeInfo.request); + // Verify the route is configured with a request property + assert.ok(PostCalculateMinerFeeInfo.request); }); it('should have the correct response types', function () { - assert.ok(PostV1CalculateMinerFeeInfo.response[200]); - assert.ok(PostV1CalculateMinerFeeInfo.response[400]); - assert.ok(PostV1CalculateMinerFeeInfo.response[404]); - }); - }); - - describe('PostV2CalculateMinerFeeInfo route definition', function () { - it('should have the correct path for v2', function () { - assert.strictEqual(PostV2CalculateMinerFeeInfo.path, '/api/v2/calculateminerfeeinfo'); - }); - - it('should have the correct HTTP method', function () { - assert.strictEqual(PostV2CalculateMinerFeeInfo.method, 'POST'); - }); - - it('should have the correct request configuration', function () { - assert.ok(PostV2CalculateMinerFeeInfo.request); - }); - - it('should have the correct response types', function () { - assert.ok(PostV2CalculateMinerFeeInfo.response[200]); - assert.ok(PostV2CalculateMinerFeeInfo.response[400]); - assert.ok(PostV2CalculateMinerFeeInfo.response[404]); + // Check that the response object has the expected status codes + assert.ok(PostCalculateMinerFeeInfo.response[200]); + assert.ok(PostCalculateMinerFeeInfo.response[400]); + assert.ok(PostCalculateMinerFeeInfo.response[404]); }); }); diff --git a/modules/express/test/unit/typedRoutes/ofcSignPayload.ts b/modules/express/test/unit/typedRoutes/ofcSignPayload.ts index 59cdd54f4d..2248b3e5b7 100644 --- a/modules/express/test/unit/typedRoutes/ofcSignPayload.ts +++ b/modules/express/test/unit/typedRoutes/ofcSignPayload.ts @@ -136,60 +136,6 @@ describe('OfcSignPayload codec tests', function () { assert.ok(decodedResponse); }); - it('should not double-stringify a stringified JSON payload', async function () { - const originalPayload = '{"coin":"ofctbtc","recipients":[{"address":"abc123","amount":"1000"}]}'; - const requestBody = { - walletId: 'ofc-wallet-id-123', - payload: originalPayload, - walletPassphrase: 'test_passphrase', - }; - - const mockTradingAccount = { - signPayload: sinon.stub().resolves(mockSignPayloadResponse.signature), - }; - - const mockWallet = { - id: () => requestBody.walletId, - toTradingAccount: sinon.stub().returns(mockTradingAccount), - }; - - const walletsGetStub = sinon.stub().resolves(mockWallet); - const mockWallets = { get: walletsGetStub }; - const mockCoin = { wallets: sinon.stub().returns(mockWallets) }; - sinon.stub(BitGo.prototype, 'coin').returns(mockCoin as any); - - const result = await agent - .post('/api/v2/ofc/signPayload') - .set('Authorization', 'Bearer test_access_token_12345') - .set('Content-Type', 'application/json') - .send(requestBody); - - assert.strictEqual(result.status, 200); - const decodedResponse = assertDecode(OfcSignPayloadResponse200, result.body); - - // The returned payload must not be double-stringified. - // A double-stringified payload would start with a quote character and contain escaped quotes. - assert.strictEqual( - decodedResponse.payload.startsWith('"'), - false, - 'payload was double-stringified: starts with a quote character' - ); - assert.strictEqual( - decodedResponse.payload.includes('\\"'), - false, - 'payload was double-stringified: contains escaped quotes' - ); - - // The payload passed to tradingAccount.signPayload must match the original string - const signCall = mockTradingAccount.signPayload.getCall(0); - assert.ok(signCall, 'tradingAccount.signPayload should have been called'); - assert.strictEqual( - signCall.args[0].payload, - originalPayload, - 'tradingAccount.signPayload received a different payload than the original' - ); - }); - it('should successfully sign payload without walletPassphrase (uses env)', async function () { const requestBody = { walletId: 'ofc-wallet-id-123', diff --git a/modules/sdk-api/package.json b/modules/sdk-api/package.json index 32b2bd7366..2c5ad2b2b2 100644 --- a/modules/sdk-api/package.json +++ b/modules/sdk-api/package.json @@ -49,7 +49,7 @@ "bitcoinjs-message": "npm:@bitgo-forks/bitcoinjs-message@1.0.0-master.3", "debug": "3.1.0", "eol": "^0.5.0", - "lodash": "^4.18.0", + "lodash": "^4.17.15", "proxy-agent": "6.4.0", "sanitize-html": "^2.11", "secp256k1": "5.0.1", diff --git a/modules/sdk-coin-ada/package.json b/modules/sdk-coin-ada/package.json index c7ea327498..1a17aaac84 100644 --- a/modules/sdk-coin-ada/package.json +++ b/modules/sdk-coin-ada/package.json @@ -49,7 +49,7 @@ "bignumber.js": "^9.0.2", "bs58": "^6.0.0", "cbor": "^10.0.3", - "lodash": "^4.18.0", + "lodash": "^4.17.21", "superagent": "^9.0.1", "tweetnacl": "^1.0.3" }, diff --git a/modules/sdk-coin-algo/package.json b/modules/sdk-coin-algo/package.json index 16e0734e6d..4ee34eed2f 100644 --- a/modules/sdk-coin-algo/package.json +++ b/modules/sdk-coin-algo/package.json @@ -49,7 +49,7 @@ "hi-base32": "^0.5.1", "joi": "^17.4.0", "js-sha512": "0.8.0", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "stellar-sdk": "^10.0.1", "tweetnacl": "^1.0.3" }, diff --git a/modules/sdk-coin-apt/package.json b/modules/sdk-coin-apt/package.json index 5e177315fc..9de6a7d4ed 100644 --- a/modules/sdk-coin-apt/package.json +++ b/modules/sdk-coin-apt/package.json @@ -45,7 +45,7 @@ "@bitgo/sdk-core": "^36.37.0", "@bitgo/statics": "^58.32.0", "bignumber.js": "^9.1.2", - "lodash": "^4.18.0" + "lodash": "^4.17.21" }, "devDependencies": { "@bitgo/sdk-api": "^1.76.1", diff --git a/modules/sdk-coin-avaxc/package.json b/modules/sdk-coin-avaxc/package.json index 8d3295ffed..f7453e03a6 100644 --- a/modules/sdk-coin-avaxc/package.json +++ b/modules/sdk-coin-avaxc/package.json @@ -51,7 +51,7 @@ "ethereumjs-abi": "^0.6.5", "ethereumjs-util": "7.1.5", "keccak": "^3.0.3", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "secp256k1": "5.0.1", "superagent": "^9.0.1" }, diff --git a/modules/sdk-coin-avaxp/package.json b/modules/sdk-coin-avaxp/package.json index fd553ed60f..24b152d204 100644 --- a/modules/sdk-coin-avaxp/package.json +++ b/modules/sdk-coin-avaxp/package.json @@ -56,7 +56,7 @@ "bignumber.js": "^9.0.0", "create-hash": "^1.2.0", "ethereumjs-util": "7.1.5", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "safe-buffer": "^5.2.1" }, "gitHead": "18e460ddf02de2dbf13c2aa243478188fb539f0c", diff --git a/modules/sdk-coin-cspr/package.json b/modules/sdk-coin-cspr/package.json index 01f7905123..c41a63f015 100644 --- a/modules/sdk-coin-cspr/package.json +++ b/modules/sdk-coin-cspr/package.json @@ -47,7 +47,7 @@ "@stablelib/hex": "^1.0.0", "bignumber.js": "^9.0.0", "casper-js-sdk": "2.7.6", - "lodash": "^4.18.0", + "lodash": "^4.17.15", "secp256k1": "5.0.1" }, "devDependencies": { diff --git a/modules/sdk-coin-dot/package.json b/modules/sdk-coin-dot/package.json index 46e472ce97..83e7f97b8f 100644 --- a/modules/sdk-coin-dot/package.json +++ b/modules/sdk-coin-dot/package.json @@ -72,7 +72,7 @@ "bs58": "^4.0.1", "hi-base32": "^0.5.1", "joi": "^17.4.0", - "lodash": "^4.18.0", + "lodash": "^4.17.15", "tweetnacl": "^1.0.3" }, "devDependencies": { diff --git a/modules/sdk-coin-eos/package.json b/modules/sdk-coin-eos/package.json index 5ac2ca9853..d615f1b69a 100644 --- a/modules/sdk-coin-eos/package.json +++ b/modules/sdk-coin-eos/package.json @@ -46,7 +46,7 @@ "bignumber.js": "^9.0.2", "eosjs": "^21.0.2", "eosjs-ecc": "^4.0.4", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "superagent": "^9.0.1" }, "devDependencies": { diff --git a/modules/sdk-coin-etc/package.json b/modules/sdk-coin-etc/package.json index cac8691338..41bb1cd44d 100644 --- a/modules/sdk-coin-etc/package.json +++ b/modules/sdk-coin-etc/package.json @@ -49,7 +49,7 @@ "bignumber.js": "^9.1.1", "ethereumjs-abi": "^0.6.5", "ethereumjs-util": "7.1.5", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "superagent": "^9.0.1" }, "devDependencies": { diff --git a/modules/sdk-coin-eth/package.json b/modules/sdk-coin-eth/package.json index 698441558d..0d75462383 100644 --- a/modules/sdk-coin-eth/package.json +++ b/modules/sdk-coin-eth/package.json @@ -50,7 +50,7 @@ "ethereumjs-abi": "^0.6.5", "ethereumjs-util": "7.1.5", "ethers": "^5.1.3", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "secp256k1": "5.0.1", "superagent": "^9.0.1" }, diff --git a/modules/sdk-coin-flr/package.json b/modules/sdk-coin-flr/package.json index 8ac516f04b..907d9441c4 100644 --- a/modules/sdk-coin-flr/package.json +++ b/modules/sdk-coin-flr/package.json @@ -51,7 +51,7 @@ "bignumber.js": "^9.0.0", "ethereumjs-util": "7.1.5", "keccak": "^3.0.0", - "lodash": "^4.18.0", + "lodash": "^4.17.21", "secp256k1": "^5.0.0" }, "devDependencies": { diff --git a/modules/sdk-coin-hbar/package.json b/modules/sdk-coin-hbar/package.json index 4f5c29d201..f8ca80e329 100644 --- a/modules/sdk-coin-hbar/package.json +++ b/modules/sdk-coin-hbar/package.json @@ -47,7 +47,7 @@ "@hashgraph/sdk": "2.72.0", "@stablelib/sha384": "^1.0.0", "bignumber.js": "^9.0.0", - "lodash": "^4.18.0", + "lodash": "^4.17.15", "long": "^5.2.3", "protobufjs": "7.2.5", "stellar-sdk": "^10.0.1", diff --git a/modules/sdk-coin-iota/package.json b/modules/sdk-coin-iota/package.json index e3df37d703..6c870a31ea 100644 --- a/modules/sdk-coin-iota/package.json +++ b/modules/sdk-coin-iota/package.json @@ -46,7 +46,7 @@ "@iota/bcs": "^1.2.0", "@iota/iota-sdk": "^1.6.0", "bignumber.js": "^9.1.2", - "lodash": "^4.18.0" + "lodash": "^4.17.21" }, "devDependencies": { "@bitgo/sdk-api": "^1.76.1", diff --git a/modules/sdk-coin-near/package.json b/modules/sdk-coin-near/package.json index 49527992ed..ee5e80899a 100644 --- a/modules/sdk-coin-near/package.json +++ b/modules/sdk-coin-near/package.json @@ -49,7 +49,7 @@ "bignumber.js": "^9.0.0", "bs58": "^4.0.1", "js-sha256": "^0.9.0", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "near-api-js": "^5.1.1", "superagent": "^9.0.1", "tweetnacl": "^1.0.3" diff --git a/modules/sdk-coin-rune/package.json b/modules/sdk-coin-rune/package.json index 017beac3fd..9f3bb5148b 100644 --- a/modules/sdk-coin-rune/package.json +++ b/modules/sdk-coin-rune/package.json @@ -49,7 +49,7 @@ "@cosmjs/stargate": "^0.29.5", "bech32-buffer": "^0.2.1", "bignumber.js": "^9.1.1", - "lodash": "^4.18.0" + "lodash": "^4.17.21" }, "devDependencies": { "@bitgo/sdk-api": "^1.76.1", diff --git a/modules/sdk-coin-sol/package.json b/modules/sdk-coin-sol/package.json index 076e957d46..3263370215 100644 --- a/modules/sdk-coin-sol/package.json +++ b/modules/sdk-coin-sol/package.json @@ -67,7 +67,7 @@ "@solana/web3.js": "1.92.1", "bignumber.js": "^9.0.0", "bs58": "^4.0.1", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "superagent": "^9.0.1", "tweetnacl": "^1.0.3" }, diff --git a/modules/sdk-coin-stx/package.json b/modules/sdk-coin-stx/package.json index 8d0d53fb79..7e4bc58152 100644 --- a/modules/sdk-coin-stx/package.json +++ b/modules/sdk-coin-stx/package.json @@ -49,7 +49,7 @@ "bignumber.js": "^9.0.0", "bn.js": "^5.2.1", "ethereumjs-util": "7.1.5", - "lodash": "^4.18.0" + "lodash": "^4.17.15" }, "devDependencies": { "@bitgo/sdk-api": "^1.76.1", diff --git a/modules/sdk-coin-sui/package.json b/modules/sdk-coin-sui/package.json index 81b4bd4fdf..50e1b73530 100644 --- a/modules/sdk-coin-sui/package.json +++ b/modules/sdk-coin-sui/package.json @@ -47,7 +47,7 @@ "@mysten/bcs": "^0.7.0", "bignumber.js": "^9.0.0", "bs58": "^4.0.1", - "lodash": "^4.18.0", + "lodash": "^4.17.21", "superagent": "3.8.2", "superstruct": "^1.0.3", "tweetnacl": "^1.0.3" diff --git a/modules/sdk-coin-ton/package.json b/modules/sdk-coin-ton/package.json index c0b291cc8d..d5d9f43e84 100644 --- a/modules/sdk-coin-ton/package.json +++ b/modules/sdk-coin-ton/package.json @@ -46,7 +46,7 @@ "@bitgo/wasm-ton": "^1.1.1", "bignumber.js": "^9.0.0", "bn.js": "^5.2.1", - "lodash": "^4.18.0", + "lodash": "^4.17.21", "tonweb": "^0.0.62", "tweetnacl": "^1.0.3" }, diff --git a/modules/sdk-coin-trx/package.json b/modules/sdk-coin-trx/package.json index 7a9f361b07..8e0f0daef8 100644 --- a/modules/sdk-coin-trx/package.json +++ b/modules/sdk-coin-trx/package.json @@ -53,7 +53,7 @@ "@stablelib/hex": "^1.0.0", "bignumber.js": "^9.0.0", "ethers": "^5.7.2", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "long": "^5.3.2", "protobufjs": "7.2.5", "secp256k1": "5.0.1", diff --git a/modules/sdk-coin-vet/package.json b/modules/sdk-coin-vet/package.json index 7b2a0824b2..57d5545cb2 100644 --- a/modules/sdk-coin-vet/package.json +++ b/modules/sdk-coin-vet/package.json @@ -52,7 +52,7 @@ "bignumber.js": "^9.1.1", "ethereumjs-abi": "^0.6.5", "ethereumjs-util": "7.1.5", - "lodash": "^4.18.0", + "lodash": "^4.17.21", "tweetnacl": "^1.0.3" }, "devDependencies": { diff --git a/modules/sdk-coin-xlm/package.json b/modules/sdk-coin-xlm/package.json index 89d151f486..c019c36aaf 100644 --- a/modules/sdk-coin-xlm/package.json +++ b/modules/sdk-coin-xlm/package.json @@ -43,7 +43,7 @@ "@bitgo/sdk-core": "^36.37.0", "@bitgo/statics": "^58.32.0", "bignumber.js": "^9.1.1", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "stellar-sdk": "^10.0.1", "superagent": "^9.0.1" }, diff --git a/modules/sdk-coin-xrp/package.json b/modules/sdk-coin-xrp/package.json index 1ad0f9ba6e..ec43e704ef 100644 --- a/modules/sdk-coin-xrp/package.json +++ b/modules/sdk-coin-xrp/package.json @@ -44,7 +44,7 @@ "@bitgo/secp256k1": "^1.11.0", "@bitgo/statics": "^58.32.0", "bignumber.js": "^9.0.0", - "lodash": "^4.18.0", + "lodash": "^4.17.14", "ripple-binary-codec": "2.1.0", "ripple-keypairs": "2.0.0", "xrpl": "4.0.0" diff --git a/modules/sdk-coin-xtz/package.json b/modules/sdk-coin-xtz/package.json index 39fc47f4fa..ea6b4f27e0 100644 --- a/modules/sdk-coin-xtz/package.json +++ b/modules/sdk-coin-xtz/package.json @@ -51,7 +51,7 @@ "bignumber.js": "^9.0.0", "bs58check": "^2.1.2", "libsodium-wrappers": "^0.7.6", - "lodash": "^4.18.0", + "lodash": "^4.17.15", "superagent": "^9.0.1" }, "devDependencies": { diff --git a/modules/sdk-core/package.json b/modules/sdk-core/package.json index d9130da638..c6bb455008 100644 --- a/modules/sdk-core/package.json +++ b/modules/sdk-core/package.json @@ -61,7 +61,7 @@ "io-ts-types": "^0.5.16", "keccak": "3.0.3", "libsodium-wrappers-sumo": "^0.7.9", - "lodash": "^4.18.0", + "lodash": "^4.17.15", "noble-bls12-381": "0.7.2", "openpgp": "5.11.3", "paillier-bigint": "3.3.0", diff --git a/modules/sdk-core/src/bitgo/environments.ts b/modules/sdk-core/src/bitgo/environments.ts index b29e33b058..c13ceada50 100644 --- a/modules/sdk-core/src/bitgo/environments.ts +++ b/modules/sdk-core/src/bitgo/environments.ts @@ -347,6 +347,9 @@ const mainnetBase: EnvironmentTemplate = { h: { baseUrl: 'https://humanity-mainnet.explorer.alchemy.com/api', }, + boba: { + baseUrl: 'https://api.routescan.io/v2/network/mainnet/evm/1/etherscan/api', + }, }, icpNodeUrl: 'https://ic0.app', hyperLiquidNodeUrl: 'https://api.hyperliquid.xyz', @@ -555,6 +558,9 @@ const testnetBase: EnvironmentTemplate = { h: { baseUrl: 'https://humanity-testnet.explorer.alchemy.com/api', }, + boba: { + baseUrl: 'https://api.routescan.io/v2/network/testnet/evm/28882/etherscan/api', + }, }, stxNodeUrl: 'https://api.testnet.hiro.so', vetNodeUrl: 'https://sync-testnet.vechain.org', diff --git a/modules/statics/src/allCoinsAndTokens.ts b/modules/statics/src/allCoinsAndTokens.ts index 97bdd59b34..e029db83e9 100644 --- a/modules/statics/src/allCoinsAndTokens.ts +++ b/modules/statics/src/allCoinsAndTokens.ts @@ -2378,6 +2378,40 @@ export const allCoinsAndTokens = [ CoinFeature.SUPPORTS_ERC20, ] ), + account( + 'd055d442-03f1-4d24-b61c-5312e480e378', + 'bobaeth', + 'Boba Network', + Networks.main.boba, + 18, + UnderlyingAsset.BOBAETH, + BaseUnit.ETH, + [ + ...EVM_FEATURES, + CoinFeature.SHARED_EVM_SIGNING, + CoinFeature.SHARED_EVM_SDK, + CoinFeature.EVM_COMPATIBLE_IMS, + CoinFeature.EVM_COMPATIBLE_UI, + CoinFeature.SUPPORTS_ERC20, + ] + ), + account( + '8fc7c710-e64e-4743-8ce7-03bcf71d7723', + 'tbobaeth', + 'Boba Network Testnet', + Networks.test.boba, + 18, + UnderlyingAsset.BOBAETH, + BaseUnit.ETH, + [ + ...EVM_FEATURES, + CoinFeature.SHARED_EVM_SIGNING, + CoinFeature.SHARED_EVM_SDK, + CoinFeature.EVM_COMPATIBLE_IMS, + CoinFeature.EVM_COMPATIBLE_UI, + CoinFeature.SUPPORTS_ERC20, + ] + ), erc721Token( 'a7604e03-7f40-41f0-8efa-2e7673ac2a9f', diff --git a/modules/statics/src/base.ts b/modules/statics/src/base.ts index b225fbae76..9c97585c09 100644 --- a/modules/statics/src/base.ts +++ b/modules/statics/src/base.ts @@ -140,6 +140,7 @@ export enum CoinFamily { ARCUSDC = 'arcusdc', // ARC network TEMPO = 'tempo', // Tempo Network UNIETH = 'unieth', // Unichain + BOBAETH = 'bobaeth', // BOBA Network } /** @@ -2137,6 +2138,7 @@ export enum UnderlyingAsset { ZMT = 'zmt', ZOOM = 'zoom', ZRO = 'zro', + BOBAETH = 'bobaeth', 'ZRO-0x320' = 'zro-0x320', 'ZRO-0xFCF' = 'zro-0xfcf', 'ZRO-0xE5C' = 'zro-0xe5c', diff --git a/modules/statics/src/coins.ts b/modules/statics/src/coins.ts index 98804b437f..bfa400acff 100644 --- a/modules/statics/src/coins.ts +++ b/modules/statics/src/coins.ts @@ -31,7 +31,7 @@ import { } from './account'; import { ofcToken } from './ofc'; import { BaseCoin, CoinFeature, DynamicCoin } from './base'; -import { AmsNetworkConfigMap, AmsTokenConfig, TrimmedAmsTokenConfig } from './tokenConfig'; +import { AmsTokenConfig, TrimmedAmsTokenConfig } from './tokenConfig'; import { CoinMap } from './map'; import { BaseNetwork, getNetwork, getNetworksMap, NetworkType } from './networks'; import { networkFeatureMapForTokens } from './networkFeatureMapForTokens'; @@ -471,35 +471,6 @@ export function createTokenMapUsingConfigDetails(tokenConfigMap: Record, - networksMap: AmsNetworkConfigMap -): Record { - const featuresByNetworkName = new Map( - Object.values(networksMap).map((net): [string, string[]] => [net.name, net.features]) - ); - return Object.fromEntries( - Object.entries(coinTokenMap).map(([key, coins]) => [ - key, - coins.map((coin) => { - if (coin.isToken || coin.additionalFeatures !== undefined) return coin; - const features = featuresByNetworkName.get(coin.network.name); - return features !== undefined ? { ...coin, additionalFeatures: features } : coin; - }), - ]) - ); -} - export function createTokenMapUsingTrimmedConfigDetails( reducedTokenConfigMap: Record ): CoinMap { diff --git a/modules/statics/src/coins/ofcCoins.ts b/modules/statics/src/coins/ofcCoins.ts index 4280cbb2a7..9261329b7a 100644 --- a/modules/statics/src/coins/ofcCoins.ts +++ b/modules/statics/src/coins/ofcCoins.ts @@ -455,6 +455,22 @@ export const ofcCoins = [ ), ofc('aa7e956f-2d59-4bf6-aba6-2d51bd298150', 'ofcip', 'Story', 18, UnderlyingAsset.IP, CoinKind.CRYPTO), tofc('773b02f6-32ea-493a-bca5-13d93cb0afff', 'ofctip', 'Story Testnet', 18, UnderlyingAsset.IP, CoinKind.CRYPTO), + ofc( + '9fd3e1b0-2e67-46c6-ab3b-a9942533b9d6', + 'ofcbobaeth', + 'Boba Network', + 18, + UnderlyingAsset.BOBAETH, + CoinKind.CRYPTO + ), + tofc( + '14c7407a-0daa-4c3d-b438-8a9d2e60cc29', + 'ofctbobaeth', + 'Boba Network Testnet', + 18, + UnderlyingAsset.BOBAETH, + CoinKind.CRYPTO + ), ofc( '8b50bd47-54d4-456d-a141-09f8e90df850', 'ofczksyncera', diff --git a/modules/statics/src/networks.ts b/modules/statics/src/networks.ts index 10a777af16..960600da2a 100644 --- a/modules/statics/src/networks.ts +++ b/modules/statics/src/networks.ts @@ -2553,6 +2553,26 @@ class TempoTestnet extends Testnet implements EthereumNetwork { tokenOperationHashPrefix = '42431'; } +class Boba extends Mainnet implements EthereumNetwork { + name = 'Boba'; + family = CoinFamily.BOBAETH; + explorerUrl = 'https://bobascan.com/blockchain/transactions'; + accountExplorerUrl = 'https://bobascan.com/blockchain'; + chainId = 288; + nativeCoinOperationHashPrefix = '288'; + tokenOperationHashPrefix = '288'; +} + +class BobaTestnet extends Testnet implements EthereumNetwork { + name = 'Boba Testnet'; + family = CoinFamily.BOBAETH; + explorerUrl = 'https://bobascan.com/blockchain/transactions'; + accountExplorerUrl = 'https://bobascan.com/blockchain'; + chainId = 288; + nativeCoinOperationHashPrefix = '288'; + tokenOperationHashPrefix = '288'; +} + /** * Constructor options for {@link DynamicNetwork}. * Accepts string-typed `type` and `family` so AMS JSON can be passed directly. @@ -2763,6 +2783,7 @@ export const Networks = { zkSync: Object.freeze(new ZkSync()), zkSyncEra: Object.freeze(new ZkSyncEra()), unieth: Object.freeze(new Unieth()), + boba: Object.freeze(new Boba()), }, test: { ada: Object.freeze(new AdaTestnet()), @@ -2889,6 +2910,7 @@ export const Networks = { zkSync: Object.freeze(new ZkSyncTestnet()), zkSyncEra: Object.freeze(new ZkSyncEraTestnet()), unieth: Object.freeze(new UniethTestnet()), + boba: Object.freeze(new BobaTestnet()), }, }; diff --git a/modules/statics/src/tokenConfig.ts b/modules/statics/src/tokenConfig.ts index b76b11592f..4f96c3269b 100644 --- a/modules/statics/src/tokenConfig.ts +++ b/modules/statics/src/tokenConfig.ts @@ -42,7 +42,7 @@ import { } from './account'; import { CoinFamily, CoinKind, BaseCoin, CoinFeature } from './base'; import { coins } from './coins'; -import { DynamicNetworkOptions, EthereumNetwork, Networks, NetworkType } from './networks'; +import { EthereumNetwork, Networks, NetworkType } from './networks'; import { OfcCoin } from './ofc'; export interface BaseTokenConfig { @@ -289,12 +289,6 @@ export interface AmsTokenConfig { policyId?: string; } -export interface AmsNetworkConfig extends DynamicNetworkOptions { - features: CoinFeature[]; -} - -export type AmsNetworkConfigMap = Record; - export interface TrimmedAmsNetworkConfig { name: string; } diff --git a/modules/statics/test/unit/fixtures/expectedColdFeatures.ts b/modules/statics/test/unit/fixtures/expectedColdFeatures.ts index d0e364771c..76e7486590 100644 --- a/modules/statics/test/unit/fixtures/expectedColdFeatures.ts +++ b/modules/statics/test/unit/fixtures/expectedColdFeatures.ts @@ -81,6 +81,7 @@ export const expectedColdFeatures = { 'bera', 'baseeth', 'bld', + 'bobaeth', 'bsc', 'canton', 'chiliz', @@ -156,6 +157,7 @@ export const expectedColdFeatures = { 'tbera', 'tbaseeth', 'tbld', + 'tbobaeth', 'tbsc', 'tcanton', 'tchiliz', diff --git a/modules/unspents/package.json b/modules/unspents/package.json index f99ecbf2fd..18c2334e41 100644 --- a/modules/unspents/package.json +++ b/modules/unspents/package.json @@ -37,7 +37,7 @@ }, "dependencies": { "@bitgo/utxo-lib": "^11.22.0", - "lodash": "^4.18.0", + "lodash": "~4.17.21", "tcomb": "~3.2.29", "varuint-bitcoin": "^1.0.4" }, diff --git a/modules/web-demo/package.json b/modules/web-demo/package.json index 1b6ae3d7fc..9dec73a3b8 100644 --- a/modules/web-demo/package.json +++ b/modules/web-demo/package.json @@ -66,7 +66,7 @@ "@bitgo/sjcl": "^1.1.0", "@bitgo/statics": "^58.32.0", "bitgo": "^50.29.0", - "lodash": "^4.18.0", + "lodash": "^4.17.15", "react": "^18.0.0", "react-dom": "^18.0.0", "react-json-view": "^1.21.3", diff --git a/package.json b/package.json index 13f10c100f..1dc25d994c 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,6 @@ }, "resolutions": { "qs": "6.14.1", - "**/lodash": ">=4.18.1", "**/lerna/**/glob": "11.1.0", "**/yeoman-generator/**/glob": "11.1.0", "**/cacache/glob": "11.1.0", diff --git a/yarn.lock b/yarn.lock index 3e8f1381b3..435918a175 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14591,10 +14591,10 @@ lodash.upperfirst@^4.3.1: resolved "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz" integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== -lodash@>=4.18.1, lodash@^4.17.11, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5, lodash@^4.18.0: - version "4.18.1" - resolved "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz#ff2b66c1f6326d59513de2407bf881439812771c" - integrity sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q== +lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.5, lodash@~4.17.21: + version "4.17.21" + resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-symbols@^4.0.0, log-symbols@^4.1.0: version "4.1.0"