Skip to content

Commit e9657f1

Browse files
drew-bitgoclaude
andcommitted
refactor(sdk-core,bitgo): replace per-currency fiat classes with config-driven Fiat class
Replace 36 individual fiat coin class files with a single generic Fiat class that takes a config object (chain, fullName, baseFactor). All currencies are defined in a config array and registration is automatic via a loop in coinFactory. Testnet variants are derived automatically from mainnet configs. This reduces the effort to add a new fiat currency from ~6 files and 150+ lines of boilerplate to a single config line. FIAT-311 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d067420 commit e9657f1

16 files changed

Lines changed: 130 additions & 703 deletions

File tree

modules/bitgo/src/v2/coinFactory.ts

Lines changed: 11 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,8 @@ import {
9191
HashToken,
9292
MonToken,
9393
TethLikeCoin,
94-
FiatAED,
95-
FiatEur,
96-
FiatGBP,
97-
FiatINR,
98-
FiatSGD,
99-
FiatUsd,
94+
Fiat,
95+
allFiatCoins,
10096
Gteth,
10197
Hash,
10298
Hbar,
@@ -171,12 +167,6 @@ import {
171167
Teth,
172168
Tflr,
173169
Tmon,
174-
TfiatAED,
175-
TfiatEur,
176-
TfiatGBP,
177-
TfiatINR,
178-
TfiatSGD,
179-
TfiatUsd,
180170
Thash,
181171
Thbar,
182172
Tia,
@@ -274,12 +264,9 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin
274264
coinFactory.register('topbnb', TethLikeCoin.createInstance);
275265
coinFactory.register('tfantom', TethLikeCoin.createInstance);
276266
coinFactory.register('tbaseeth', TethLikeCoin.createInstance);
277-
coinFactory.register('fiataed', FiatAED.createInstance);
278-
coinFactory.register('fiateur', FiatEur.createInstance);
279-
coinFactory.register('fiatgbp', FiatGBP.createInstance);
280-
coinFactory.register('fiatinr', FiatINR.createInstance);
281-
coinFactory.register('fiatsgd', FiatSGD.createInstance);
282-
coinFactory.register('fiatusd', FiatUsd.createInstance);
267+
for (const fiatCoin of allFiatCoins) {
268+
coinFactory.register(fiatCoin.chain, Fiat.createConstructor(fiatCoin));
269+
}
283270
coinFactory.register('flr', Flr.createInstance);
284271
coinFactory.register('flrp', Flrp.createInstance);
285272
coinFactory.register('gteth', Gteth.createInstance);
@@ -346,12 +333,6 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin
346333
coinFactory.register('teos', Teos.createInstance);
347334
coinFactory.register('tetc', Tetc.createInstance);
348335
coinFactory.register('teth', Teth.createInstance);
349-
coinFactory.register('tfiataed', TfiatAED.createInstance);
350-
coinFactory.register('tfiateur', TfiatEur.createInstance);
351-
coinFactory.register('tfiatgbp', TfiatGBP.createInstance);
352-
coinFactory.register('tfiatinr', TfiatINR.createInstance);
353-
coinFactory.register('tfiatsgd', TfiatSGD.createInstance);
354-
coinFactory.register('tfiatusd', TfiatUsd.createInstance);
355336
coinFactory.register('tflr', Tflr.createInstance);
356337
coinFactory.register('tflrp', Flrp.createInstance);
357338
coinFactory.register('tmon', Tmon.createInstance);
@@ -693,18 +674,6 @@ export function getCoinConstructor(coinName: string): CoinConstructor | undefine
693674
return TethLikeCoin.createInstance;
694675
case 'tfantom':
695676
return TethLikeCoin.createInstance;
696-
case 'fiataed':
697-
return FiatAED.createInstance;
698-
case 'fiateur':
699-
return FiatEur.createInstance;
700-
case 'fiatgbp':
701-
return FiatGBP.createInstance;
702-
case 'fiatinr':
703-
return FiatINR.createInstance;
704-
case 'fiatsgd':
705-
return FiatSGD.createInstance;
706-
case 'fiatusd':
707-
return FiatUsd.createInstance;
708677
case 'flr':
709678
return Flr.createInstance;
710679
case 'flrp':
@@ -837,18 +806,6 @@ export function getCoinConstructor(coinName: string): CoinConstructor | undefine
837806
return Tetc.createInstance;
838807
case 'teth':
839808
return Teth.createInstance;
840-
case 'tfiataed':
841-
return TfiatAED.createInstance;
842-
case 'tfiateur':
843-
return TfiatEur.createInstance;
844-
case 'tfiatgbp':
845-
return TfiatGBP.createInstance;
846-
case 'tfiatinr':
847-
return TfiatINR.createInstance;
848-
case 'tfiatsgd':
849-
return TfiatSGD.createInstance;
850-
case 'tfiatusd':
851-
return TfiatUsd.createInstance;
852809
case 'tflr':
853810
return Tflr.createInstance;
854811
case 'tflrp':
@@ -957,8 +914,13 @@ export function getCoinConstructor(coinName: string): CoinConstructor | undefine
957914
return Zeta.createInstance;
958915
case 'zketh':
959916
return Zketh.createInstance;
960-
default:
917+
default: {
918+
const fiatConfig = allFiatCoins.find((c) => c.chain === coinName);
919+
if (fiatConfig) {
920+
return Fiat.createConstructor(fiatConfig);
921+
}
961922
return undefined;
923+
}
962924
}
963925
}
964926

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

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -155,39 +155,5 @@ export { World, Tworld, WorldToken };
155155
export { Zketh, Tzketh, ZkethToken };
156156

157157
import { coins } from '@bitgo/sdk-core';
158-
const {
159-
Ofc,
160-
OfcToken,
161-
Susd,
162-
FiatUsd,
163-
FiatEur,
164-
FiatGBP,
165-
FiatINR,
166-
FiatAED,
167-
FiatSGD,
168-
Tsusd,
169-
TfiatUsd,
170-
TfiatEur,
171-
TfiatGBP,
172-
TfiatINR,
173-
TfiatAED,
174-
TfiatSGD,
175-
} = coins;
176-
export {
177-
FiatAED,
178-
FiatEur,
179-
FiatGBP,
180-
FiatINR,
181-
FiatSGD,
182-
FiatUsd,
183-
Ofc,
184-
OfcToken,
185-
Susd,
186-
TfiatAED,
187-
TfiatEur,
188-
TfiatGBP,
189-
TfiatINR,
190-
TfiatSGD,
191-
TfiatUsd,
192-
Tsusd,
193-
};
158+
const { Ofc, OfcToken, Susd, Tsusd, Fiat, allFiatCoins, fiatCoins, testnetFiatCoins } = coins;
159+
export { Fiat, allFiatCoins, fiatCoins, testnetFiatCoins, Ofc, OfcToken, Susd, Tsusd };

modules/sdk-core/src/coins/fiat.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/**
2+
* @prettier
3+
*/
4+
import {
5+
AuditDecryptedKeyParams,
6+
BaseCoin,
7+
BitGoBase,
8+
CoinConstructor,
9+
KeyPair,
10+
MethodNotImplementedError,
11+
ParsedTransaction,
12+
ParseTransactionOptions,
13+
SignedTransaction,
14+
SignTransactionOptions,
15+
VerifyAddressOptions,
16+
VerifyTransactionOptions,
17+
} from '../';
18+
19+
export interface FiatCoinConfig {
20+
chain: string;
21+
fullName: string;
22+
baseFactor: number;
23+
}
24+
25+
export class Fiat extends BaseCoin {
26+
private readonly config: FiatCoinConfig;
27+
28+
constructor(bitgo: BitGoBase, config: FiatCoinConfig) {
29+
super(bitgo);
30+
this.config = config;
31+
}
32+
33+
static createConstructor(config: FiatCoinConfig): CoinConstructor {
34+
return (bitgo: BitGoBase) => new Fiat(bitgo, config);
35+
}
36+
37+
getBaseFactor() {
38+
return this.config.baseFactor;
39+
}
40+
41+
getChain() {
42+
return this.config.chain;
43+
}
44+
45+
getFamily() {
46+
return 'fiat';
47+
}
48+
49+
getFullName() {
50+
return this.config.fullName;
51+
}
52+
53+
isValidMofNSetup({ m, n }: { m: number; n: number }) {
54+
return m === 0 && n === 0;
55+
}
56+
57+
isValidAddress(address: string): boolean {
58+
throw new MethodNotImplementedError();
59+
}
60+
61+
generateKeyPair(seed?: Buffer): KeyPair {
62+
throw new MethodNotImplementedError();
63+
}
64+
65+
isValidPub(pub: string): boolean {
66+
throw new MethodNotImplementedError();
67+
}
68+
69+
async parseTransaction(params: ParseTransactionOptions): Promise<ParsedTransaction> {
70+
return {};
71+
}
72+
73+
async isWalletAddress(params: VerifyAddressOptions): Promise<boolean> {
74+
throw new MethodNotImplementedError();
75+
}
76+
77+
async verifyTransaction(params: VerifyTransactionOptions): Promise<boolean> {
78+
return true;
79+
}
80+
81+
async signTransaction(params: SignTransactionOptions = {}): Promise<SignedTransaction> {
82+
throw new MethodNotImplementedError();
83+
}
84+
85+
/** @inheritDoc */
86+
auditDecryptedKey(params: AuditDecryptedKeyParams): void {
87+
throw new MethodNotImplementedError();
88+
}
89+
}
90+
91+
/**
92+
* Configuration for all fiat currencies.
93+
* To add a new fiat currency, just add an entry here — registration is automatic.
94+
*/
95+
export const fiatCoins: FiatCoinConfig[] = [
96+
{ chain: 'fiataed', fullName: 'United Arab Emirates Dirham', baseFactor: 1e2 },
97+
{ chain: 'fiateur', fullName: 'European Union Euro', baseFactor: 1e2 },
98+
{ chain: 'fiatgbp', fullName: 'British Pound Sterling', baseFactor: 1e2 },
99+
{ chain: 'fiatinr', fullName: 'Indian Rupee', baseFactor: 1e2 },
100+
{ chain: 'fiatsgd', fullName: 'Singapore Dollar', baseFactor: 1e2 },
101+
{ chain: 'fiatusd', fullName: 'USD Dollar', baseFactor: 1e2 },
102+
];
103+
104+
/**
105+
* Testnet configs derived automatically from mainnet configs.
106+
*/
107+
export const testnetFiatCoins: FiatCoinConfig[] = fiatCoins.map((c) => ({
108+
chain: `t${c.chain}`,
109+
fullName: `Testnet ${c.fullName}`,
110+
baseFactor: c.baseFactor,
111+
}));
112+
113+
/**
114+
* All fiat coin configs (mainnet + testnet).
115+
*/
116+
export const allFiatCoins: FiatCoinConfig[] = [...fiatCoins, ...testnetFiatCoins];

modules/sdk-core/src/coins/fiataed.ts

Lines changed: 0 additions & 82 deletions
This file was deleted.

0 commit comments

Comments
 (0)