Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
bc3f700
feat/starknet-utils
ljankovic-txfusion May 9, 2025
f0d7677
feat/starknet-sdk-integration
ljankovic-txfusion May 9, 2025
14d3792
Merge remote-tracking branch 'origin/feat/starknet-core-abi-exports' …
ljankovic-txfusion May 15, 2025
6a8299d
Merge remote-tracking branch 'origin/feat/starknet-utils' into feat/s…
ljankovic-txfusion May 15, 2025
5cc1b15
Merge remote-tracking branch 'origin/feat/starknet-core-abi-exports' …
ljankovic-txfusion May 15, 2025
b784a1e
Merge remote-tracking branch 'origin/feat/starknet-utils' into feat/s…
ljankovic-txfusion May 15, 2025
cc61fdb
fix: changelog typos (#6234)
paulbalaji May 15, 2025
5b833e8
chore: update svm igp config (#6236)
xeno097 May 15, 2025
f8696c7
feat: Add Starknet contract ABI fetching and contract artifact genera…
ljankovic-txfusion May 15, 2025
1482467
feat: add tUSD/eclipsemainnet-ethereum warp route (#6220)
antigremlin May 15, 2025
ecf82fa
Merge remote-tracking branch 'origin/main' into feat/starknet-utils
ljankovic-txfusion May 16, 2025
a0c584d
Merge remote-tracking branch 'origin/feat/starknet-utils' into feat/s…
ljankovic-txfusion May 16, 2025
0de63e0
feat: add Starknet address and transaction utilities [STARKNET-02] (#…
ljankovic-txfusion May 16, 2025
b98468d
fix: monorepo docker builds (#6245)
paulbalaji May 16, 2025
b906c0e
Merge remote-tracking branch 'origin/main' into feat/starknet-utils
ljankovic-txfusion May 16, 2025
0580192
Merge remote-tracking branch 'origin/feat/starknet-utils' into feat/s…
ljankovic-txfusion May 16, 2025
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
5 changes: 5 additions & 0 deletions .changeset/hip-papayas-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hyperlane-xyz/sdk': minor
---

feat: Starknet SDK logic integration
5 changes: 5 additions & 0 deletions .changeset/metal-coats-remain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@hyperlane-xyz/utils': minor
---

Add Starknet address and tx utils
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM node:20-alpine

WORKDIR /hyperlane-monorepo

RUN apk add --update --no-cache git g++ make py3-pip jq
RUN apk add --update --no-cache git g++ make py3-pip jq bash curl

RUN yarn set version 4.5.1

Expand All @@ -22,14 +22,15 @@ COPY typescript/github-proxy/package.json ./typescript/github-proxy/
COPY typescript/cosmos-types/package.json ./typescript/cosmos-types/
COPY typescript/cosmos-sdk/package.json ./typescript/cosmos-sdk/
COPY solidity/package.json ./solidity/
COPY starknet/package.json ./starknet/
COPY starknet/package.json ./starknet/

RUN yarn install && yarn cache clean

# Copy everything else
COPY tsconfig.json ./
COPY typescript ./typescript
COPY solidity ./solidity
COPY starknet ./starknet

RUN yarn build

Expand Down
40 changes: 40 additions & 0 deletions rust/sealevel/environments/mainnet3/gas-oracle-configs.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@
},
"overhead": 600000
},
"abstract": {
"oracleConfig": {
"tokenExchangeRate": "187056373229658428214",
"gasPrice": "193418836",
"tokenDecimals": 18
},
"overhead": 333774
},
"artela": {
"oracleConfig": {
"tokenExchangeRate": "152446195501249",
Expand Down Expand Up @@ -194,6 +202,22 @@
}
},
"eclipsemainnet": {
"sonicsvm": {
"oracleConfig": {
"tokenExchangeRate": "120284594486260",
"gasPrice": "35603",
"tokenDecimals": 9
},
"overhead": 600000
},
"soon": {
"oracleConfig": {
"tokenExchangeRate": "1500000000000000",
"gasPrice": "2855",
"tokenDecimals": 9
},
"overhead": 600000
},
"ethereum": {
"oracleConfig": {
"tokenExchangeRate": "15000000000000000000",
Expand Down Expand Up @@ -243,9 +267,25 @@
"tokenDecimals": 18
},
"overhead": 159736
},
"eclipsemainnet": {
"oracleConfig": {
"tokenExchangeRate": "1500000000000000",
"gasPrice": "2855",
"tokenDecimals": 9
},
"overhead": 600000
}
},
"sonicsvm": {
"eclipsemainnet": {
"oracleConfig": {
"tokenExchangeRate": "18705637322965842",
"gasPrice": "2855",
"tokenDecimals": 9
},
"overhead": 600000
},
"solanamainnet": {
"oracleConfig": {
"tokenExchangeRate": "1500000000000000",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"eclipsemainnet": {
"hex": "0x3c141cbabe775eb1cb82d357bed3724e39e4fd2de256aee2a69de336d360d97a",
"base58": "53XFTNcTRTzrNyD3QodXbRBZ249G8v3iSHh8FzYeHZoX"
},
"ethereum": {
"hex": "0x00000000000000000000000069b1a59e98d94e1b9647c08cb295fc52597d20f0",
"base58": "1111111111112UQUH3pY5HJ7m8iy1sgSB5Gs9dvX"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"eclipsemainnet": {
"type": "synthetic",
"decimals": 6,
"remoteDecimals": 6,
"name": "Turbo USD",
"symbol": "tUSD",
"uri": "https://raw.githubusercontent.com/hyperlane-xyz/hyperlane-registry/71b97e47ffe47348b2ea9cb1bde344ca78daea50/deployments/warp_routes/tUSD/metadata.json",
"interchainGasPaymaster": "3Wp4qKkgf4tjXz1soGyTSndCgBPLZFSrZkiDZ8Qp9EEj"
},
"ethereum": {
"type": "collateral",
"decimals": 6,
"token": "0x722a851B6798D65b80526562Fc3a36E19b1F883b",
"foreignDeployment": "0x69B1A59e98D94E1B9647C08Cb295Fc52597D20f0"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,11 @@ function getChainConnections(
['svmbnb', 'solanamainnet'],
['svmbnb', 'bsc'],
['svmbnb', 'soon'],
['sonicsvm', 'eclipsemainnet'],
['soon', 'solanamainnet'],
['soon', 'bsc'],
['soon', 'eclipsemainnet'],
['abstract', 'solanamainnet'],
// All warp routes
...Object.values(WarpRouteIds).map(getWarpChains),
];
Expand Down
2 changes: 1 addition & 1 deletion typescript/sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
- d182d7d: Adds the sortArraysInObject function to properly sort arrays in an object recursively given an optional sort function
- 248d2e1: Enables the CLI to warp check routes that include non EVM routes
- e2a4727: Deploy to new chains: ontology, miraclechain, kyve.
- b360802: Add the isCosmosIbcDenomAddress function and improve the config expasion logic to correctly format the destination gas
- b360802: Add the isCosmosIbcDenomAddress function and improve the config expansion logic to correctly format the destination gas
- 31ee1c6: Adds fiatCollateral token on chain config derivation logic as it was incorrectly inferred as collateral
- a36d5c1: add cosmos native hook module & reader

Expand Down
1 change: 1 addition & 0 deletions typescript/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"@cosmjs/stargate": "^0.32.4",
"@hyperlane-xyz/core": "7.1.5",
"@hyperlane-xyz/cosmos-sdk": "12.6.0",
"@hyperlane-xyz/starknet-core": "1.0.0",
"@hyperlane-xyz/utils": "12.6.0",
"@safe-global/api-kit": "1.3.0",
"@safe-global/protocol-kit": "1.3.0",
Expand Down
9 changes: 9 additions & 0 deletions typescript/sdk/src/app/MultiProtocolApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
CosmJsWasmProvider,
EthersV5Provider,
SolanaWeb3Provider,
StarknetJsProvider,
TypedProvider,
} from '../providers/ProviderType.js';
import { ChainMap, ChainName } from '../types.js';
Expand Down Expand Up @@ -104,6 +105,14 @@ export class BaseSealevelAdapter extends BaseAppAdapter {
}
}

export class BaseStarknetAdapter extends BaseAppAdapter {
public readonly protocol: ProtocolType = ProtocolType.Starknet;

public getProvider(): StarknetJsProvider['provider'] {
return this.multiProvider.getStarknetProvider(this.chainName);
}
}

/**
* A version of HyperlaneApp that can support different
* provider types across different protocol types.
Expand Down
19 changes: 19 additions & 0 deletions typescript/sdk/src/consts/testChains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,32 @@ export const testSealevelChain: ChainMetadata = {
rpcUrls: [{ http: 'http://127.0.0.1:8899' }],
};

export const testStarknetChain: ChainMetadata = {
chainId: '0x534e5f5345504f4c4941',
domainId: 5854809,
name: 'starknetdevnet',
nativeToken: {
decimals: 18,
denom: '0x49D36570D4E46F48E99674BD3FCC84644DDD6B96F7C741B1562B82F9E004DC7',
name: 'Ether',
symbol: 'ETH',
},
protocol: ProtocolType.Starknet,
rpcUrls: [
{
http: 'http://127.0.0.1:5050',
},
],
};

export const multiProtocolTestChainMetadata: ChainMap<ChainMetadata> = {
...testChainMetadata,
testcosmos: testCosmosChain,
testsealevel: testSealevelChain,
testxerc20: testXERC20,
testvsxerc20: testVSXERC20,
testxerc20lockbox: testXERC20Lockbox,
starknetdevnet: testStarknetChain,
};

export const multiProtocolTestChains: Array<ChainName> = Object.keys(
Expand Down
2 changes: 2 additions & 0 deletions typescript/sdk/src/core/MultiProtocolCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CosmNativeCoreAdapter } from './adapters/CosmNativeCoreAdapter.js';
import { CosmWasmCoreAdapter } from './adapters/CosmWasmCoreAdapter.js';
import { EvmCoreAdapter } from './adapters/EvmCoreAdapter.js';
import { SealevelCoreAdapter } from './adapters/SealevelCoreAdapter.js';
import { StarknetCoreAdapter } from './adapters/StarknetCoreAdapter.js';
import { ICoreAdapter } from './adapters/types.js';
import { CoreAddresses } from './contracts.js';

Expand Down Expand Up @@ -41,6 +42,7 @@ export class MultiProtocolCore extends MultiProtocolApp<
if (protocol === ProtocolType.Sealevel) return SealevelCoreAdapter;
if (protocol === ProtocolType.Cosmos) return CosmWasmCoreAdapter;
if (protocol === ProtocolType.CosmosNative) return CosmNativeCoreAdapter;
if (protocol === ProtocolType.Starknet) return StarknetCoreAdapter;
throw new Error(`No adapter for protocol ${protocol}`);
}

Expand Down
127 changes: 127 additions & 0 deletions typescript/sdk/src/core/adapters/StarknetCoreAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import {
CallData,
InvokeTransactionReceiptResponse,
ParsedEvents,
events as eventsUtils,
} from 'starknet';

import { getCompiledContract } from '@hyperlane-xyz/starknet-core';
import { Address, HexString, pollAsync } from '@hyperlane-xyz/utils';

import { BaseStarknetAdapter } from '../../app/MultiProtocolApp.js';
import { MultiProtocolProvider } from '../../providers/MultiProtocolProvider.js';
import {
ProviderType,
StarknetJsTransactionReceipt,
} from '../../providers/ProviderType.js';
import { ChainName } from '../../types.js';
import {
getStarknetMailboxContract,
parseStarknetDispatchEvents,
} from '../../utils/starknet.js';

import { ICoreAdapter } from './types.js';

export class StarknetCoreAdapter
extends BaseStarknetAdapter
implements ICoreAdapter
{
constructor(
public readonly chainName: ChainName,
public readonly multiProvider: MultiProtocolProvider,
public readonly addresses: { mailbox: Address },
) {
super(chainName, multiProvider, addresses);
}

extractMessageIds(
sourceTx: StarknetJsTransactionReceipt,
): Array<{ messageId: string; destination: ChainName }> {
if (sourceTx.type !== ProviderType.Starknet) {
throw new Error(
`Unsupported provider type for StarknetCoreAdapter ${sourceTx.type}`,
);
}

let parsedEvents: ParsedEvents = [];
sourceTx.receipt.match({
success: (txR) => {
const emittedEvents =
(txR as InvokeTransactionReceiptResponse).events?.map((event) => {
return {
block_hash: (txR as any).block_hash,
block_number: (txR as any).block_number,
transaction_hash: (txR as any).transaction_hash,
...event,
};
}) || [];

if (emittedEvents.length === 0) return;
const mailboxAbi = getCompiledContract('mailbox').abi;
parsedEvents = eventsUtils.parseEvents(
emittedEvents,
eventsUtils.getAbiEvents(mailboxAbi),
CallData.getAbiStruct(mailboxAbi),
CallData.getAbiEnum(mailboxAbi),
);
},
_: () => {
throw Error('This transaction was not successful.');
},
});

if (!parsedEvents || parsedEvents.length === 0) return [];

const messages = parseStarknetDispatchEvents(
parsedEvents,
(domain) => this.multiProvider.tryGetChainName(domain) ?? undefined,
);

return messages.map(({ id, parsed }) => ({
messageId: id,
destination: this.multiProvider.getChainName(parsed.destination),
}));
}

async waitForMessageProcessed(
messageId: HexString,
destination: ChainName,
delayMs = 5000,
maxAttempts = 60,
): Promise<boolean> {
const destAdapter = new StarknetCoreAdapter(
destination,
this.multiProvider,
{ mailbox: this.addresses.mailbox },
);

const mailboxContract = getStarknetMailboxContract(
destAdapter.addresses.mailbox,
destAdapter.getProvider(),
);

await pollAsync(
async () => {
const isDelivered = await mailboxContract.call('delivered', [
messageId,
]);

if (!isDelivered) {
throw new Error(
`Message ${messageId} not yet delivered on ${destination}`,
);
}

this.logger.debug(
`Message ${messageId} confirmed delivered on ${destination}`,
);

return isDelivered;
},
delayMs,
maxAttempts,
);

return true;
}
}
14 changes: 14 additions & 0 deletions typescript/sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export {
export { CosmWasmCoreAdapter } from './core/adapters/CosmWasmCoreAdapter.js';
export { EvmCoreAdapter } from './core/adapters/EvmCoreAdapter.js';
export { SealevelCoreAdapter } from './core/adapters/SealevelCoreAdapter.js';
export { StarknetCoreAdapter } from './core/adapters/StarknetCoreAdapter.js';
export { ICoreAdapter } from './core/adapters/types.js';
export {
CoreAddresses,
Expand Down Expand Up @@ -366,6 +367,10 @@ export {
SolanaWeb3Provider,
SolanaWeb3Transaction,
SolanaWeb3TransactionReceipt,
StarknetJsContract,
StarknetJsProvider,
StarknetJsTransaction,
StarknetJsTransactionReceipt,
TypedContract,
TypedProvider,
TypedTransaction,
Expand Down Expand Up @@ -712,3 +717,12 @@ export {
CCIPContractCache,
} from './ccip/utils.js';
export { HyperlaneCCIPDeployer } from './ccip/HyperlaneCCIPDeployer.js';

export {
StarknetContractName,
getStarknetContract,
getStarknetHypERC20Contract,
getStarknetHypERC20CollateralContract,
getStarknetMailboxContract,
getStarknetEtherContract,
} from './utils/starknet.js';
Loading