Skip to content

Commit 6afaed3

Browse files
authored
Merge pull request #8131 from BitGo/SC-5394
feat(irys): update package structure for irys
2 parents ba550e5 + ac9409f commit 6afaed3

14 files changed

Lines changed: 278 additions & 1 deletion

File tree

modules/bitgo/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
"@bitgo/sdk-coin-initia": "^2.5.0",
9191
"@bitgo/sdk-coin-injective": "^3.6.0",
9292
"@bitgo/sdk-coin-iota": "^1.8.0",
93+
"@bitgo/sdk-coin-irys": "^1.0.0",
9394
"@bitgo/sdk-coin-islm": "^2.5.0",
9495
"@bitgo/sdk-coin-lnbtc": "^1.6.0",
9596
"@bitgo/sdk-coin-ltc": "^3.7.0",

modules/bitgo/src/v2/coinFactory.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ import {
105105
Initia,
106106
Injective,
107107
Iota,
108+
Irys,
108109
Islm,
109110
JettonToken,
110111
Lnbtc,
@@ -183,6 +184,7 @@ import {
183184
Ticp,
184185
Tinitia,
185186
Tinjective,
187+
TIrys,
186188
Tislm,
187189
Tlnbtc,
188190
Tltc,
@@ -293,6 +295,7 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin
293295
coinFactory.register('initia', Initia.createInstance);
294296
coinFactory.register('injective', Injective.createInstance);
295297
coinFactory.register('iota', Iota.createInstance);
298+
coinFactory.register('irys', Irys.createInstance);
296299
coinFactory.register('islm', Islm.createInstance);
297300
coinFactory.register('near', Near.createInstance);
298301
coinFactory.register('oas', Oas.createInstance);
@@ -361,6 +364,7 @@ export function registerCoinConstructors(coinFactory: CoinFactory, coinMap: Coin
361364
coinFactory.register('tinitia', Tinitia.createInstance);
362365
coinFactory.register('tinjective', Tinjective.createInstance);
363366
coinFactory.register('tiota', Iota.createInstance);
367+
coinFactory.register('tirys', TIrys.createInstance);
364368
coinFactory.register('tislm', Tislm.createInstance);
365369
coinFactory.register('tlnbtc', Tlnbtc.createInstance);
366370
coinFactory.register('tltc', Tltc.createInstance);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import { Icp, Ticp } from '@bitgo/sdk-coin-icp';
4242
import { Initia, Tinitia } from '@bitgo/sdk-coin-initia';
4343
import { Injective, Tinjective } from '@bitgo/sdk-coin-injective';
4444
import { Iota } from '@bitgo/sdk-coin-iota';
45+
import { Irys, TIrys } from '@bitgo/sdk-coin-irys';
4546
import { Islm, Tislm } from '@bitgo/sdk-coin-islm';
4647
import { Lnbtc, Tlnbtc } from '@bitgo/sdk-coin-lnbtc';
4748
import { Ltc, Tltc } from '@bitgo/sdk-coin-ltc';
@@ -118,6 +119,7 @@ export { Hbar, Thbar };
118119
export { Icp, Ticp };
119120
export { Initia, Tinitia };
120121
export { Iota };
122+
export { Irys, TIrys };
121123
export { Lnbtc, Tlnbtc };
122124
export { Ltc, Tltc };
123125
export { Mon, Tmon, MonToken };

modules/bitgo/tsconfig.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,9 @@
182182
{
183183
"path": "../sdk-coin-iota"
184184
},
185+
{
186+
"path": "../sdk-coin-irys"
187+
},
185188
{
186189
"path": "../sdk-coin-islm"
187190
},

modules/sdk-coin-irys/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,18 @@
4040
]
4141
},
4242
"dependencies": {
43+
"@bitgo/abstract-eth": "^24.20.0",
44+
"@bitgo/sdk-core": "^36.30.0",
45+
"@bitgo/statics": "^58.24.0",
46+
"@ethereumjs/common": "^2.6.5",
4347
"@ethereumjs/rlp": "^4.0.0",
4448
"bs58": "^4.0.1",
4549
"ethers": "^5.1.3",
4650
"superagent": "^9.0.1"
4751
},
4852
"devDependencies": {
53+
"@bitgo/sdk-api": "^1.73.4",
54+
"@bitgo/sdk-test": "^9.1.25",
4955
"@types/sinon": "^10.0.11",
5056
"@types/superagent": "^8.1.0",
5157
"nock": "^13.3.1",

modules/sdk-coin-irys/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1+
export * from './irys';
2+
export * from './tirys';
3+
export * from './register';
14
export * from './lib';

modules/sdk-coin-irys/src/irys.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { BaseCoin, BitGoBase, MPCAlgorithm } from '@bitgo/sdk-core';
2+
import { AbstractEthLikeNewCoins } from '@bitgo/abstract-eth';
3+
import { CoinFeature, BaseCoin as StaticsBaseCoin, coins, EthereumNetwork } from '@bitgo/statics';
4+
import { IrysCommitmentTransactionBuilder, TransactionBuilder } from './lib';
5+
6+
/**
7+
* Irys coin implementation.
8+
*
9+
* Irys is EVM-compatible for standard transfers (inherits from AbstractEthLikeNewCoins)
10+
* but uses custom commitment transactions for staking (STAKE, PLEDGE, etc.).
11+
*
12+
* Standard EVM operations (transfers, balance queries) use the inherited EVM logic.
13+
* Commitment transactions use the IrysCommitmentTransactionBuilder.
14+
*/
15+
export class Irys extends AbstractEthLikeNewCoins {
16+
protected constructor(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>) {
17+
super(bitgo, staticsCoin);
18+
}
19+
20+
static createInstance(bitgo: BitGoBase, staticsCoin?: Readonly<StaticsBaseCoin>): BaseCoin {
21+
return new Irys(bitgo, staticsCoin);
22+
}
23+
24+
/**
25+
* Irys supports TSS (from EVM_FEATURES in statics).
26+
*/
27+
supportsTss(): boolean {
28+
return this.staticsCoin?.features.includes(CoinFeature.TSS) ?? false;
29+
}
30+
31+
/** @inheritdoc */
32+
getMPCAlgorithm(): MPCAlgorithm {
33+
return 'ecdsa';
34+
}
35+
36+
/**
37+
* Get the Irys native API URL from the network config.
38+
* This is the non-EVM API used for commitment transactions.
39+
*/
40+
getIrysApiUrl(): string | undefined {
41+
const network = this.getNetwork() as EthereumNetwork;
42+
return network.irysApiUrl;
43+
}
44+
45+
/**
46+
* Create a commitment transaction builder for staking operations.
47+
* This is separate from getTransactionBuilder() which handles standard EVM transfers.
48+
*/
49+
getCommitmentTransactionBuilder(): IrysCommitmentTransactionBuilder {
50+
const apiUrl = this.getIrysApiUrl();
51+
if (!apiUrl) {
52+
throw new Error('Irys API URL is not configured for this network');
53+
}
54+
return new IrysCommitmentTransactionBuilder(apiUrl, BigInt(this.getChainId()));
55+
}
56+
57+
/**
58+
* Create a new transaction builder for standard EVM transactions.
59+
* @return a new transaction builder
60+
*/
61+
protected getTransactionBuilder(): TransactionBuilder {
62+
return new TransactionBuilder(coins.get(this.getBaseChain()));
63+
}
64+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
export * from './iface';
22
export * from './commitmentTransactionBuilder';
3+
export * from './transactionBuilder';
34
export * from './utils';
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { BaseCoin as CoinConfig, EthereumNetwork, CoinFeature, NetworkType } from '@bitgo/statics';
2+
import { BuildTransactionError, TransactionType } from '@bitgo/sdk-core';
3+
import {
4+
TransactionBuilder as AbstractTransactionBuilder,
5+
Transaction,
6+
TransferBuilder,
7+
getCommon as getAbstractCommon,
8+
} from '@bitgo/abstract-eth';
9+
import EthereumCommon from '@ethereumjs/common';
10+
11+
/**
12+
* Get the Ethereum common configuration for Irys.
13+
* @param coin - The coin configuration
14+
* @returns Ethereum common configuration object
15+
*/
16+
function getCommon(coin: Readonly<CoinConfig>): EthereumCommon {
17+
return EthereumCommon.custom(
18+
{
19+
name: coin.network.name,
20+
networkId: (coin.network as EthereumNetwork).chainId,
21+
chainId: (coin.network as EthereumNetwork).chainId,
22+
},
23+
{
24+
baseChain: coin.network.type === NetworkType.MAINNET ? 'mainnet' : 'sepolia',
25+
hardfork: coin.features.includes(CoinFeature.EIP1559) ? 'london' : undefined,
26+
eips: coin.features.includes(CoinFeature.EIP1559) ? [1559] : undefined,
27+
}
28+
);
29+
}
30+
31+
/**
32+
* Irys transaction builder for standard EVM transactions.
33+
*/
34+
export class TransactionBuilder extends AbstractTransactionBuilder {
35+
protected _transfer: TransferBuilder;
36+
37+
constructor(_coinConfig: Readonly<CoinConfig>) {
38+
super(_coinConfig);
39+
this._common = getCommon(this._coinConfig);
40+
this.transaction = new Transaction(this._coinConfig, this._common);
41+
}
42+
43+
/** @inheritdoc */
44+
transfer(data?: string): TransferBuilder {
45+
if (this._type !== TransactionType.Send) {
46+
throw new BuildTransactionError('Transfers can only be set for send transactions');
47+
}
48+
if (!this._transfer) {
49+
this._transfer = new TransferBuilder(data);
50+
}
51+
return this._transfer;
52+
}
53+
54+
/**
55+
* Get contract data for wallet initialization.
56+
*
57+
* This method is intentionally not implemented for Irys. Irys uses commitment
58+
* transactions (STAKE, PLEDGE) for staking operations, which are built via
59+
* IrysCommitmentTransactionBuilder, not through standard EVM contract calls.
60+
* Standard EVM transfers work normally via the inherited transfer() method.
61+
*
62+
* @throws Error - Always throws as this is not supported for Irys
63+
*/
64+
protected getContractData(addresses: string[]): string {
65+
throw new Error(
66+
'getContractData is not implemented for Irys. Use IrysCommitmentTransactionBuilder for staking operations.'
67+
);
68+
}
69+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { BitGoBase } from '@bitgo/sdk-core';
2+
import { Irys } from './irys';
3+
import { TIrys } from './tirys';
4+
5+
export const register = (sdk: BitGoBase): void => {
6+
sdk.register('irys', Irys.createInstance);
7+
sdk.register('tirys', TIrys.createInstance);
8+
};

0 commit comments

Comments
 (0)