Skip to content

Commit

Permalink
feat(AllbridgeCoreSdkOptions): add partnerId
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonKozAllB committed Aug 2, 2024
1 parent e0c8821 commit 59f5c02
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 18 deletions.
10 changes: 6 additions & 4 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
import { formatAddress } from "../services/bridge/utils";

import { convertFloatAmountToInt, convertIntAmountToFloat, getFeePercent } from "../utils/calculation";
import { addPartnerIdToValue } from "../utils/utils";
import tokensGroupedByChain from "./data/tokens-info/ChainDetailsMap.json";
import tokenInfoWithChainDetailsGrl from "./data/tokens-info/TokenInfoWithChainDetails-GRL.json";
import tokenInfoWithChainDetailsTrx from "./data/tokens-info/TokenInfoWithChainDetails-TRX.json";
Expand Down Expand Up @@ -716,7 +717,7 @@ describe("SDK", () => {
expect(methodSendRawTransactionSpy).toHaveBeenCalledWith({
from: fromAccountAddress,
to: grlChainToken.bridgeAddress,
value: fee,
value: addPartnerIdToValue(fee),
data: expectedData,
});

Expand Down Expand Up @@ -796,7 +797,7 @@ describe("SDK", () => {
expect(methodTriggerSmartContractMock).toBeCalledWith(
trxChainToken.bridgeAddress,
"swapAndBridge(bytes32,uint256,bytes32,uint256,bytes32,uint256,uint8,uint256)",
{ callValue: fee },
{ callValue: addPartnerIdToValue(fee) },
[
{
type: "bytes32",
Expand Down Expand Up @@ -892,7 +893,7 @@ describe("SDK", () => {
expect(methodSendRawTransactionSpy).toHaveBeenCalledWith({
from: fromAccountAddress,
to: grlChainToken.bridgeAddress,
value: "0",
value: addPartnerIdToValue("0"),
data: expectedData,
});

Expand Down Expand Up @@ -935,6 +936,7 @@ describe("SDK", () => {
data: "0x331838b20000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000ddac3cb57dea3fbeff4997d78215535eb5787117000000000000000000000000c7dbc4a896b34b7a10dda2ef72052145a9122f4300000000000000000000000068d7ed9cf9881427f1db299b90fd63ef805dd10d0000000000000000000000000000000000000000000000006124fee993bc0000",
from: "0x68D7ed9cf9881427F1dB299B90Fd63ef805dd10d",
to: "0xba285A8F52601EabCc769706FcBDe2645aa0AF18",
value: addPartnerIdToValue("0"),
});
});
test("rawTxBuilder should build swapTx correctly for trx", async () => {
Expand Down Expand Up @@ -967,7 +969,7 @@ describe("SDK", () => {
expect(methodTriggerSmartContractMock).toBeCalledWith(
trxChainToken.bridgeAddress,
"swap(uint256,bytes32,bytes32,address,uint256)",
{ callValue: "0" },
{ callValue: addPartnerIdToValue("0") },
[
{
type: "uint256",
Expand Down
6 changes: 4 additions & 2 deletions src/__tests__/services/bridge/evm/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import Web3 from "web3";
import { Messenger } from "../../../../client/core-api/core-api.model";
import { AllbridgeCoreClientWithPoolInfo } from "../../../../client/core-api/core-client-base";
import { AllbridgeCoreSdkOptions } from "../../../../index";
import { FeePaymentMethod, SendParams, TokenWithChainDetails } from "../../../../models";
import { NodeRpcUrlsConfig } from "../../../../services";
import { EvmBridgeService } from "../../../../services/bridge/evm";
import { ChainDetailsMapWithFlags } from "../../../../tokens-info";
import { addPartnerIdToValue } from "../../../../utils/utils";
import tokensGroupedByChain from "../../../data/tokens-info/ChainDetailsMap-ETH-USDT.json";
import { mockNonce } from "../../../mock/bridge/utils";
import { initChainsWithTestnet } from "../../../mock/utils";
Expand All @@ -26,7 +28,7 @@ describe("EvmBridge", () => {
};

beforeEach(() => {
evmBridge = new EvmBridgeService(new Web3(), api, new NodeRpcUrlsConfig({}));
evmBridge = new EvmBridgeService(new Web3(), api, new NodeRpcUrlsConfig({}), {} as AllbridgeCoreSdkOptions);
});

describe("Given transfer params", () => {
Expand Down Expand Up @@ -63,7 +65,7 @@ describe("EvmBridge", () => {
expect(actual).toEqual({
from: from,
to: bridgeAddress,
value: gasFee,
value: addPartnerIdToValue(gasFee),
data: "0x4cd480bd000000000000000000000000c7dbc4a896b34b7a10dda2ef72052145a9122f4300000000000000000000000000000000000000000000000012751bf40f450000000000000000000000000000ba285a8f52601eabcc769706fcbde2645aa0af180000000000000000000000000000000000000000000000000000000000000004000000000000000000000000b10388f04f8331b59a02732cc1b6ac0d7045574b3b1200153e110000001b006132000000000000000000362600611e000000070c00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000",
});
});
Expand Down
10 changes: 8 additions & 2 deletions src/__tests__/services/bridge/trx/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import TronWeb from "tronweb";
import { ChainType } from "../../../../chains/chain.enums";
import { Messenger } from "../../../../client/core-api/core-api.model";
import { AllbridgeCoreClientWithPoolInfo } from "../../../../client/core-api/core-client-base";
import { AllbridgeCoreSdkOptions } from "../../../../index";
import { ChainSymbol, FeePaymentMethod } from "../../../../models";
import { TxSendParams } from "../../../../services/bridge/models";
import { TronBridgeService } from "../../../../services/bridge/trx";
import { formatAddress } from "../../../../services/bridge/utils";
import { addPartnerIdToValue } from "../../../../utils/utils";
import { mockNonce } from "../../../mock/bridge/utils";
import triggerSmartContractSendResponse from "../../../mock/tron-web/trigger-smart-contract-send.json";

Expand All @@ -23,7 +25,11 @@ describe("TrxBridge", () => {
triggerSmartContract: jest.fn(),
},
};
trxBridge = new TronBridgeService(tronWebMock as typeof TronWeb, api as AllbridgeCoreClientWithPoolInfo);
trxBridge = new TronBridgeService(
tronWebMock as typeof TronWeb,
api as AllbridgeCoreClientWithPoolInfo,
{} as AllbridgeCoreSdkOptions
);
});

afterEach(() => {
Expand Down Expand Up @@ -68,7 +74,7 @@ describe("TrxBridge", () => {
expect(tronWebMock.transactionBuilder.triggerSmartContract).toHaveBeenCalledWith(
bridgeAddress,
"swapAndBridge(bytes32,uint256,bytes32,uint256,bytes32,uint256,uint8,uint256)",
{ callValue: gasFee },
{ callValue: addPartnerIdToValue(gasFee) },
[
{
type: "bytes32",
Expand Down
68 changes: 68 additions & 0 deletions src/__tests__/utils/utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { InvalidAmountError } from "../../exceptions";
import { addPartnerIdToValue, validatePartnerId } from "../../utils/utils";

describe("validatePartnerId", () => {
it("should not throw an error if partnerId is not provided", () => {
expect(() => validatePartnerId()).not.toThrow();
});

it("should not throw an error if partnerId is within valid range", () => {
expect(() => validatePartnerId(1)).not.toThrow();
expect(() => validatePartnerId(65535)).not.toThrow();
expect(() => validatePartnerId(0xffff)).not.toThrow();
});

it("should throw an error if partnerId is less than 0", () => {
expect(() => validatePartnerId(-1)).toThrow(InvalidAmountError);
expect(() => validatePartnerId(-1)).toThrow("Partner Id must be > 0");
expect(() => validatePartnerId(0)).toThrow("Partner Id must be > 0");
});

it("should throw an error if partnerId is greater than 65535", () => {
expect(() => validatePartnerId(65536)).toThrow(InvalidAmountError);
expect(() => validatePartnerId(65536)).toThrow("Partner Id must be < 0xffff (65535)");
expect(() => validatePartnerId(0x10000)).toThrow("Partner Id must be < 0xffff (65535)");
});
});

describe("addPartnerIdToValue", () => {
describe("no partnerId", () => {
const testCases = [
{ input: "0", expected: "0x0" },
{ input: "100", expected: "0x0" },
{ input: "55000", expected: "0x0" },
{ input: "75000", expected: "0x10000" },
{ input: "175000", expected: "0x20000" },
{ input: "6175000", expected: "0x5e0000" },
];

test.each(testCases)("no partnerId $input", ({ input, expected }) => {
const result = addPartnerIdToValue(input);
expect(result).toEqual(expected);
});
});
describe("with partnerId", () => {
const testCases = [
{ input: "0", expected: "0x1", partnerId: 0x1 },
{ input: "0", expected: "0x123", partnerId: 0x123 },
{ input: "0", expected: "0x1234", partnerId: 0x1234 },
{ input: "0", expected: "0xffff", partnerId: 65535 },
{ input: "100", expected: "0x1", partnerId: 0x1 },
{ input: "55000", expected: "0x1", partnerId: 0x1 },
{ input: "55000", expected: "0x123", partnerId: 0x123 },
{ input: "55000", expected: "0x1234", partnerId: 0x1234 },
{ input: "75000", expected: "0x10123", partnerId: 0x123 },
{ input: "175000", expected: "0x21234", partnerId: 0x1234 },
{ input: "175000", expected: "0x2ffff", partnerId: 65535 },
{ input: "6175123", expected: "0x5e0001", partnerId: 0x1 },
{ input: "6175123", expected: "0x5e0123", partnerId: 0x123 },
{ input: "6175123", expected: "0x5e1234", partnerId: 0x1234 },
{ input: "6175123", expected: "0x5effff", partnerId: 65535 },
];

test.each(testCases)("partnerId $partnerId input $input", ({ input, expected, partnerId }) => {
const result = addPartnerIdToValue(input, partnerId);
expect(result).toEqual(expected);
});
});
});
7 changes: 7 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ export interface AllbridgeCoreSdkOptions {
* Optional additional properties to merge with the default properties.
*/
additionalChainsProperties?: Record<string, BasicChainProperties>;

/**
* Represents an optional identifier for a partner.
*
* @property {number} [partnerId] - The partner ID. This number should be greater than 0 and less than 0xffff (65535).
*/
partnerId?: number;
}

/**
Expand Down
12 changes: 10 additions & 2 deletions src/services/bridge/evm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Web3 from "web3";
import { TransactionConfig } from "web3-core";
import { AbiItem } from "web3-utils";
import { AllbridgeCoreClient } from "../../../client/core-api/core-client-base";
import { AllbridgeCoreSdkOptions } from "../../../index";
import {
ChainSymbol,
ChainType,
Expand All @@ -15,6 +16,7 @@ import {
SwapParams,
TransactionResponse,
} from "../../../models";
import { addPartnerIdToValue } from "../../../utils/utils";
import { NodeRpcUrlsConfig } from "../../index";
import { RawTransaction } from "../../models";
import bridgeAbi from "../../models/abi/Bridge.json";
Expand All @@ -31,7 +33,12 @@ import { formatAddress, getNonce, prepareTxSendParams, prepareTxSwapParams } fro
export class EvmBridgeService extends ChainBridgeService {
chainType: ChainType.EVM = ChainType.EVM;

constructor(public web3: Web3, public api: AllbridgeCoreClient, private nodeRpcUrlsConfig: NodeRpcUrlsConfig) {
constructor(
public web3: Web3,
public api: AllbridgeCoreClient,
private nodeRpcUrlsConfig: NodeRpcUrlsConfig,
private sdkOptions: AllbridgeCoreSdkOptions
) {
super();
}

Expand Down Expand Up @@ -69,6 +76,7 @@ export class EvmBridgeService extends ChainBridgeService {
return Promise.resolve({
from: fromAccountAddress,
to: contractAddress,
value: addPartnerIdToValue("0", this.sdkOptions.partnerId),
data: swapMethod.encodeABI(),
});
}
Expand Down Expand Up @@ -133,7 +141,7 @@ export class EvmBridgeService extends ChainBridgeService {
return Promise.resolve({
from: fromAccountAddress,
to: contractAddress,
value: value,
value: addPartnerIdToValue(value, this.sdkOptions.partnerId),
data: sendMethod.encodeABI(),
});
}
Expand Down
8 changes: 4 additions & 4 deletions src/services/bridge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,18 +150,18 @@ export function getChainBridgeService(
switch (Chains.getChainProperty(chainSymbol).chainType) {
case ChainType.EVM: {
if (provider) {
return new EvmBridgeService(provider as unknown as Web3, api, nodeRpcUrlsConfig);
return new EvmBridgeService(provider as unknown as Web3, api, nodeRpcUrlsConfig, params);
} else {
const nodeRpcUrl = nodeRpcUrlsConfig.getNodeRpcUrl(chainSymbol);
return new EvmBridgeService(new Web3(nodeRpcUrl), api, nodeRpcUrlsConfig);
return new EvmBridgeService(new Web3(nodeRpcUrl), api, nodeRpcUrlsConfig, params);
}
}
case ChainType.TRX: {
if (provider) {
return new TronBridgeService(provider, api);
return new TronBridgeService(provider, api, params);
} else {
const nodeRpcUrl = nodeRpcUrlsConfig.getNodeRpcUrl(chainSymbol);
return new TronBridgeService(new TronWeb({ fullHost: nodeRpcUrl }), api);
return new TronBridgeService(new TronWeb({ fullHost: nodeRpcUrl }), api, params);
}
}
case ChainType.SOLANA: {
Expand Down
10 changes: 8 additions & 2 deletions src/services/bridge/trx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import TronWeb from "tronweb";
import { ChainType } from "../../../chains/chain.enums";
import { AllbridgeCoreClient } from "../../../client/core-api/core-client-base";
import { SdkError } from "../../../exceptions";
import { AllbridgeCoreSdkOptions } from "../../../index";
import { FeePaymentMethod, Messenger, SwapParams, TransactionResponse } from "../../../models";
import { addPartnerIdToValue } from "../../../utils/utils";
import { RawTransaction, SmartContractMethodParameter } from "../../models";
import { sendRawTransaction } from "../../utils/trx";
import { SendParams, TxSendParams, TxSwapParams } from "../models";
Expand All @@ -14,7 +16,11 @@ import { getNonce, prepareTxSendParams, prepareTxSwapParams } from "../utils";
export class TronBridgeService extends ChainBridgeService {
chainType: ChainType.TRX = ChainType.TRX;

constructor(public tronWeb: typeof TronWeb, public api: AllbridgeCoreClient) {
constructor(
public tronWeb: typeof TronWeb,
public api: AllbridgeCoreClient,
private sdkOptions: AllbridgeCoreSdkOptions
) {
super();
}

Expand Down Expand Up @@ -141,7 +147,7 @@ export class TronBridgeService extends ChainBridgeService {
contractAddress,
methodSignature,
{
callValue: value,
callValue: addPartnerIdToValue(value, this.sdkOptions.partnerId),
},
parameters,
fromAddress
Expand Down
3 changes: 2 additions & 1 deletion src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
swapAndBridgeFeeCalculation,
swapAndBridgeFeeCalculationReverse,
} from "../utils/calculation/swap-and-bridge-fee-calc";
import { getPoolInfoByToken, validateAmountDecimals, validateAmountGtZero } from "../utils/utils";
import { getPoolInfoByToken, validateAmountDecimals, validateAmountGtZero, validatePartnerId } from "../utils/utils";
import { BridgeService, DefaultBridgeService } from "./bridge";
import { GetNativeTokenBalanceParams } from "./bridge/models";
import { getExtraGasMaxLimits, getGasFeeOptions } from "./bridge/utils";
Expand Down Expand Up @@ -81,6 +81,7 @@ export class AllbridgeCoreSdkService {
pool: LiquidityPoolService;

constructor(nodeRpcUrlsConfig: NodeRpcUrlsConfig, params: AllbridgeCoreSdkOptions = mainnet) {
validatePartnerId(params.partnerId);
Chains.addChainsProperties(params.additionalChainsProperties);
const apiClient = new ApiClientImpl(params);
const apiClientCaching = new ApiClientCaching(apiClient);
Expand Down
31 changes: 31 additions & 0 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,39 @@
import { Big, BigSource } from "big.js";
import BN from "bn.js";
import { AllbridgeCoreClientPoolsExt } from "../client/core-api/core-client-pool-info-caching";
import { ArgumentInvalidDecimalsError, InvalidAmountError, TimeoutError } from "../exceptions";
import { PoolInfo, TokenWithChainDetails } from "../tokens-info";

export function validatePartnerId(partnerId?: number): void {
if (partnerId || partnerId === 0) {
if (partnerId <= 0) {
throw new InvalidAmountError("Partner Id must be > 0");
}
if (partnerId > 65535) {
throw new InvalidAmountError("Partner Id must be < 0xffff (65535)");
}
}
}

export function addPartnerIdToValue(value: string, partnerId?: number): string {
let number = new BN(value, 10);
let hexString = number.toString("hex").padStart(6, "0");

hexString = hexString.slice(0, -4);

if (partnerId) {
const partnerIdHex = new BN(partnerId).toString(16).padStart(4, "0");
hexString += partnerIdHex.slice(0, 2) + partnerIdHex.slice(2);
} else {
hexString += "0000";
}

hexString = hexString.replace(/^0+/, "");
number = new BN(hexString, "hex");

return "0x" + number.toString("hex").padStart(hexString.length, "0");
}

export async function getPoolInfoByToken(
api: AllbridgeCoreClientPoolsExt,
sourceChainToken: TokenWithChainDetails
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
"allowJs": true,
"strictNullChecks": true,
"noUncheckedIndexedAccess": true
}
},
}

0 comments on commit 59f5c02

Please sign in to comment.