Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions modules/bitgo/src/v2/coinFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,12 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin
}
);

CantonToken.createTokenConstructors([...tokens.bitcoin.canton.tokens, ...tokens.testnet.canton.tokens]).forEach(
({ name, coinConstructor }) => {
coinFactory.register(name, coinConstructor);
}
);

HbarToken.createTokenConstructors([...tokens.bitcoin.hbar.tokens, ...tokens.testnet.hbar.tokens]).forEach(
({ name, coinConstructor }) => {
coinFactory.register(name, coinConstructor);
Expand Down
15 changes: 14 additions & 1 deletion modules/sdk-coin-canton/src/register.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BitGoBase } from '@bitgo/sdk-core';
import { BitGoBase, GlobalCoinFactory } from '@bitgo/sdk-core';
import { type CoinMap, getFormattedCantonTokens } from '@bitgo/statics';
import { Canton } from './canton';
import { Tcanton } from './tcanton';
import { CantonToken } from './cantonToken';
Expand All @@ -10,3 +11,15 @@ export const register = (sdk: BitGoBase): void => {
sdk.register(name, coinConstructor);
});
};

export const registerWithCoinMap = (sdk: BitGoBase, coinMap: CoinMap): void => {
sdk.register('canton', Canton.createInstance);
sdk.register('tcanton', Tcanton.createInstance);
// Registration for Canton tokens from the coin map (includes both hardcoded and dynamic tokens from AMS).
CantonToken.createTokenConstructors(getFormattedCantonTokens(coinMap)).forEach(({ name, coinConstructor }) => {
sdk.register(name, coinConstructor);
if (coinMap.has(name)) {
GlobalCoinFactory.registerToken(coinMap.get(name), coinConstructor);
}
});
};
75 changes: 75 additions & 0 deletions modules/sdk-coin-canton/test/unit/register.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import sinon from 'sinon';
import assert from 'assert';
import { BitGoAPI } from '@bitgo/sdk-api';
import { GlobalCoinFactory } from '@bitgo/sdk-core';
import { coins, CantonToken } from '@bitgo/statics';
import { register, registerWithCoinMap } from '../../src/register';
import { CantonToken as SdkCantonToken } from '../../src/cantonToken';

describe('Canton Register', function () {
let bitgo: BitGoAPI;
let registerSpy: sinon.SinonSpy;
let registerTokenSpy: sinon.SinonSpy;

beforeEach(function () {
bitgo = new BitGoAPI({ env: 'test' });
registerSpy = sinon.spy(bitgo, 'register');
registerTokenSpy = sinon.spy(GlobalCoinFactory, 'registerToken');
});

afterEach(function () {
registerSpy.restore();
registerTokenSpy.restore();
});

describe('register', function () {
it('should register base coins and token constructors', function () {
register(bitgo);

const registeredNames = registerSpy.getCalls().map((call) => call.args[0]);

// Base coins should be registered
assert.ok(registeredNames.includes('canton'));
assert.ok(registeredNames.includes('tcanton'));

// Canton tokens from statics should be registered
const cantonTokenCount = SdkCantonToken.createTokenConstructors().length;
assert.strictEqual(registerSpy.callCount, 2 + cantonTokenCount);
});
});

describe('registerWithCoinMap', function () {
it('should call register internally for base coins and tokens', function () {
registerWithCoinMap(bitgo, coins);

const registeredNames = registerSpy.getCalls().map((call) => call.args[0]);

// Base coins should be registered
assert.ok(registeredNames.includes('canton'));
assert.ok(registeredNames.includes('tcanton'));
});

it('should add dynamic Canton tokens to the global coin map', function () {
registerWithCoinMap(bitgo, coins);

// registerToken should have been called for Canton tokens in the coin map
assert.ok(registerTokenSpy.callCount > 0);

// Each call should pass a valid coin from the coinMap
for (let i = 0; i < registerTokenSpy.callCount; i++) {
const call = registerTokenSpy.getCall(i);
const staticsCoin = call.args[0];
assert.ok(coins.has(staticsCoin.name), `${staticsCoin.name} should exist in the coin map`);
}
});

it('should not add tokens to the global coin map when coin map has no Canton tokens', function () {
const limitedCoinMap = coins.filter((coin) => !(coin instanceof CantonToken));

registerWithCoinMap(bitgo, limitedCoinMap);

// registerToken should not be called since no Canton tokens are in the map
assert.strictEqual(registerTokenSpy.callCount, 0);
});
});
});
Loading