diff --git a/solidity/package.json b/solidity/package.json
index cc1ed89cc4..80367ab22e 100644
--- a/solidity/package.json
+++ b/solidity/package.json
@@ -1,10 +1,10 @@
{
"name": "@hyperlane-xyz/core",
"description": "Core solidity contracts for Hyperlane",
- "version": "3.1.0-beta0",
+ "version": "3.1.0-beta3",
"dependencies": {
"@eth-optimism/contracts": "^0.6.0",
- "@hyperlane-xyz/utils": "3.1.0-beta0",
+ "@hyperlane-xyz/utils": "3.1.0-beta3",
"@openzeppelin/contracts": "^4.8.0",
"@openzeppelin/contracts-upgradeable": "^4.8.0"
},
diff --git a/typescript/helloworld/package.json b/typescript/helloworld/package.json
index 5b95890f78..99a231521d 100644
--- a/typescript/helloworld/package.json
+++ b/typescript/helloworld/package.json
@@ -1,10 +1,10 @@
{
"name": "@hyperlane-xyz/helloworld",
"description": "A basic skeleton of an Hyperlane app",
- "version": "3.1.0-beta0",
+ "version": "3.1.0-beta3",
"dependencies": {
- "@hyperlane-xyz/core": "3.1.0-beta0",
- "@hyperlane-xyz/sdk": "3.1.0-beta0",
+ "@hyperlane-xyz/core": "3.1.0-beta3",
+ "@hyperlane-xyz/sdk": "3.1.0-beta3",
"@openzeppelin/contracts-upgradeable": "^4.8.0",
"ethers": "^5.7.2"
},
diff --git a/typescript/infra/package.json b/typescript/infra/package.json
index 1cdba73ed7..d0dc0a7c71 100644
--- a/typescript/infra/package.json
+++ b/typescript/infra/package.json
@@ -1,7 +1,7 @@
{
"name": "@hyperlane-xyz/infra",
"description": "Infrastructure utilities for the Hyperlane Network",
- "version": "1.5.1",
+ "version": "3.1.0-beta3",
"dependencies": {
"@arbitrum/sdk": "^3.0.0",
"@aws-sdk/client-iam": "^3.74.0",
@@ -11,9 +11,9 @@
"@ethersproject/experimental": "^5.7.0",
"@ethersproject/hardware-wallets": "^5.7.0",
"@ethersproject/providers": "^5.7.2",
- "@hyperlane-xyz/helloworld": "3.1.0-beta0",
- "@hyperlane-xyz/sdk": "3.1.0-beta0",
- "@hyperlane-xyz/utils": "3.1.0-beta0",
+ "@hyperlane-xyz/helloworld": "3.1.0-beta3",
+ "@hyperlane-xyz/sdk": "3.1.0-beta3",
+ "@hyperlane-xyz/utils": "3.1.0-beta3",
"@nomiclabs/hardhat-etherscan": "^3.0.3",
"@safe-global/api-kit": "^1.3.0",
"@safe-global/protocol-kit": "^1.2.0",
diff --git a/typescript/sdk/logos/black/cosmos.svg b/typescript/sdk/logos/black/cosmos.svg
new file mode 100644
index 0000000000..5f8ab7b33d
--- /dev/null
+++ b/typescript/sdk/logos/black/cosmos.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/typescript/sdk/logos/black/cosmwasm.svg b/typescript/sdk/logos/black/cosmwasm.svg
new file mode 100644
index 0000000000..bef563f624
--- /dev/null
+++ b/typescript/sdk/logos/black/cosmwasm.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/typescript/sdk/logos/black/manta.svg b/typescript/sdk/logos/black/manta.svg
new file mode 100644
index 0000000000..43e1691fc6
--- /dev/null
+++ b/typescript/sdk/logos/black/manta.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/typescript/sdk/logos/black/neutron.svg b/typescript/sdk/logos/black/neutron.svg
new file mode 100644
index 0000000000..5f541609e1
--- /dev/null
+++ b/typescript/sdk/logos/black/neutron.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/typescript/sdk/logos/color/cosmos.svg b/typescript/sdk/logos/color/cosmos.svg
new file mode 100644
index 0000000000..6023d57e6a
--- /dev/null
+++ b/typescript/sdk/logos/color/cosmos.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/typescript/sdk/logos/color/cosmwasm.svg b/typescript/sdk/logos/color/cosmwasm.svg
new file mode 100644
index 0000000000..21df94390a
--- /dev/null
+++ b/typescript/sdk/logos/color/cosmwasm.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/typescript/sdk/logos/color/manta.svg b/typescript/sdk/logos/color/manta.svg
new file mode 100644
index 0000000000..65ea376986
--- /dev/null
+++ b/typescript/sdk/logos/color/manta.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/typescript/sdk/logos/color/neutron.svg b/typescript/sdk/logos/color/neutron.svg
new file mode 100644
index 0000000000..5f541609e1
--- /dev/null
+++ b/typescript/sdk/logos/color/neutron.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/typescript/sdk/package.json b/typescript/sdk/package.json
index 18f4514dc2..2ca61790a5 100644
--- a/typescript/sdk/package.json
+++ b/typescript/sdk/package.json
@@ -1,17 +1,18 @@
{
"name": "@hyperlane-xyz/sdk",
"description": "The official SDK for the Hyperlane Network",
- "version": "3.1.0-beta0",
+ "version": "3.1.0-beta3",
"dependencies": {
"@cosmjs/cosmwasm-stargate": "^0.31.3",
"@cosmjs/stargate": "^0.31.3",
- "@hyperlane-xyz/core": "3.1.0-beta0",
- "@hyperlane-xyz/utils": "3.1.0-beta0",
+ "@hyperlane-xyz/core": "3.1.0-beta3",
+ "@hyperlane-xyz/utils": "3.1.0-beta3",
"@solana/spl-token": "^0.3.8",
"@solana/web3.js": "^1.78.0",
"@types/coingecko-api": "^1.0.10",
"@types/debug": "^4.1.7",
"@wagmi/chains": "^0.2.6",
+ "bignumber.js": "^9.1.1",
"coingecko-api": "^1.0.10",
"cosmjs-types": "^0.9.0",
"cross-fetch": "^3.1.5",
diff --git a/typescript/sdk/src/consts/chainMetadata.ts b/typescript/sdk/src/consts/chainMetadata.ts
index 1b7d753852..d95960b0b6 100644
--- a/typescript/sdk/src/consts/chainMetadata.ts
+++ b/typescript/sdk/src/consts/chainMetadata.ts
@@ -814,6 +814,7 @@ export const neutron: ChainMetadata = {
{
name: 'Mintscan',
url: 'https://www.mintscan.io/neutron',
+ // TODO API not actually supported, using url to meet validation requirements
apiUrl: 'https://www.mintscan.io/neutron',
family: ExplorerFamily.Other,
},
diff --git a/typescript/sdk/src/index.ts b/typescript/sdk/src/index.ts
index 23a3efdaf4..2eff41891a 100644
--- a/typescript/sdk/src/index.ts
+++ b/typescript/sdk/src/index.ts
@@ -294,6 +294,11 @@ export {
CwNativeTokenAdapter,
CwTokenAdapter,
} from './token/adapters/CosmWasmTokenAdapter';
+export {
+ CosmIbcToWarpTokenAdapter,
+ CosmIbcTokenAdapter,
+ CosmNativeTokenAdapter,
+} from './token/adapters/CosmosTokenAdapter';
export {
EvmHypCollateralAdapter,
EvmHypSyntheticAdapter,
diff --git a/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts b/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts
index 594018cf99..10249bca11 100644
--- a/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts
+++ b/typescript/sdk/src/token/adapters/CosmWasmTokenAdapter.ts
@@ -1,5 +1,6 @@
import { ExecuteInstruction } from '@cosmjs/cosmwasm-stargate';
import { Coin } from '@cosmjs/stargate';
+import BigNumber from 'bignumber.js';
import {
Address,
@@ -370,8 +371,27 @@ export class CwHypNativeAdapter
if (!txValue) {
throw new Error('txValue is required for native tokens');
}
-
const collateralDenom = await this.denom();
+
+ const funds: Coin[] =
+ collateralDenom === this.gasDenom
+ ? [
+ {
+ amount: new BigNumber(weiAmountOrId).plus(txValue).toFixed(0),
+ denom: collateralDenom,
+ },
+ ]
+ : [
+ {
+ amount: weiAmountOrId.toString(),
+ denom: collateralDenom,
+ },
+ {
+ amount: txValue.toString(),
+ denom: this.gasDenom,
+ },
+ ];
+
return this.cw20adapter.prepareRouter(
{
transfer_remote: {
@@ -380,16 +400,7 @@ export class CwHypNativeAdapter
amount: weiAmountOrId.toString(),
},
},
- [
- {
- amount: weiAmountOrId.toString(),
- denom: collateralDenom,
- },
- {
- amount: txValue.toString(),
- denom: this.gasDenom,
- },
- ],
+ funds,
);
}
}
diff --git a/typescript/sdk/src/token/adapters/CosmosTokenAdapter.ts b/typescript/sdk/src/token/adapters/CosmosTokenAdapter.ts
index 9830265a24..ab482fdbfa 100644
--- a/typescript/sdk/src/token/adapters/CosmosTokenAdapter.ts
+++ b/typescript/sdk/src/token/adapters/CosmosTokenAdapter.ts
@@ -1,31 +1,44 @@
import { MsgTransferEncodeObject } from '@cosmjs/stargate';
-import { MsgTransfer } from 'cosmjs-types/ibc/applications/transfer/v1/tx';
+import Long from 'long';
-import { Address } from '@hyperlane-xyz/utils';
+import { Address, Domain } from '@hyperlane-xyz/utils';
import { BaseCosmosAdapter } from '../../app/MultiProtocolApp';
import { MultiProtocolProvider } from '../../providers/MultiProtocolProvider';
+import { ChainName } from '../../types';
import { MinimalTokenMetadata } from '../config';
-import { ITokenAdapter, TransferParams } from './ITokenAdapter';
+import { CwHypCollateralAdapter } from './CosmWasmTokenAdapter';
+import {
+ IHypTokenAdapter,
+ ITokenAdapter,
+ TransferParams,
+ TransferRemoteParams,
+} from './ITokenAdapter';
-// Interacts with IBC denom tokens
-export class NativeTokenAdapter
+const COSMOS_IBC_TRANSFER_TIMEOUT = 600_000; // 10 minutes
+
+// Interacts with native tokens on a Cosmos chain (e.g TIA on Celestia)
+export class CosmNativeTokenAdapter
extends BaseCosmosAdapter
implements ITokenAdapter
{
constructor(
- public readonly chainName: string,
+ public readonly chainName: ChainName,
public readonly multiProvider: MultiProtocolProvider,
public readonly addresses: Record,
- public readonly ibcDenom: string = 'untrn',
+ public readonly properties: {
+ ibcDenom: string;
+ },
) {
+ if (!properties.ibcDenom)
+ throw new Error('Missing properties for CosmNativeTokenAdapter');
super(chainName, multiProvider, addresses);
}
async getBalance(address: string): Promise {
const provider = await this.getProvider();
- const coin = await provider.getBalance(address, this.ibcDenom);
+ const coin = await provider.getBalance(address, this.properties.ibcDenom);
return coin.amount;
}
@@ -38,28 +51,140 @@ export class NativeTokenAdapter
}
async populateTransferTx(
- transferParams: TransferParams,
+ _transferParams: TransferParams,
+ ): Promise {
+ throw new Error('TODO not yet implemented');
+ }
+}
+
+// Interacts with native tokens on a Cosmos chain and adds support for IBC transfers
+// This implements the IHypTokenAdapter interface but it's an imperfect fit as some
+// methods don't apply to IBC transfers the way they do for Warp transfers
+export class CosmIbcTokenAdapter
+ extends CosmNativeTokenAdapter
+ implements IHypTokenAdapter
+{
+ constructor(
+ public readonly chainName: ChainName,
+ public readonly multiProvider: MultiProtocolProvider,
+ public readonly addresses: Record,
+ public readonly properties: {
+ ibcDenom: string;
+ sourcePort: string;
+ sourceChannel: string;
+ },
+ ) {
+ if (
+ !properties.ibcDenom ||
+ !properties.sourcePort ||
+ !properties.sourceChannel
+ )
+ throw new Error('Missing properties for CosmNativeIbcTokenAdapter');
+ super(chainName, multiProvider, addresses, properties);
+ }
+
+ getDomains(): Promise {
+ throw new Error('Method not applicable to IBC adapters');
+ }
+ getRouterAddress(_domain: Domain): Promise {
+ throw new Error('Method not applicable to IBC adapters');
+ }
+ getAllRouters(): Promise<
+ Array<{
+ domain: Domain;
+ address: Buffer;
+ }>
+ > {
+ throw new Error('Method not applicable to IBC adapters');
+ }
+ quoteGasPayment(_destination: Domain): Promise {
+ throw new Error('Method not applicable to IBC adapters');
+ }
+
+ async populateTransferRemoteTx(
+ transferParams: TransferRemoteParams,
+ memo = '',
): Promise {
- const transfer: MsgTransfer = {
- sourcePort: '',
- sourceChannel: '',
+ if (!transferParams.fromAccountOwner)
+ throw new Error('fromAccountOwner is required for ibc transfers');
+
+ const value = {
+ sourcePort: this.properties.sourcePort,
+ sourceChannel: this.properties.sourceChannel,
token: {
- denom: this.ibcDenom,
+ denom: this.properties.ibcDenom,
amount: transferParams.weiAmountOrId.toString(),
},
- sender: '',
- receiver: '',
- timeoutHeight: {
- revisionNumber: 0n,
- revisionHeight: 0n,
- },
- timeoutTimestamp: 0n,
- memo: '', // how to encode this?
+ sender: transferParams.fromAccountOwner,
+ receiver: transferParams.recipient,
+ // Represented as nano-seconds
+ timeoutTimestamp: Long.fromNumber(
+ new Date().getTime() + COSMOS_IBC_TRANSFER_TIMEOUT,
+ ).multiply(1_000_000),
+ memo,
};
return {
typeUrl: '/ibc.applications.transfer.v1.MsgTransfer',
- // @ts-ignore
- value: transfer,
+ value,
+ };
+ }
+}
+
+// A wrapper for the CosmIbcTokenAdapter that adds support auto-initiated warp transfers
+// A.k.a. 'One-Click' cosmos to evm transfers
+export class CosmIbcToWarpTokenAdapter
+ extends CosmIbcTokenAdapter
+ implements IHypTokenAdapter
+{
+ constructor(
+ public readonly chainName: ChainName,
+ public readonly multiProvider: MultiProtocolProvider,
+ public readonly addresses: {
+ intermediateRouterAddress: Address;
+ destinationRouterAddress: Address;
+ },
+ public readonly properties: CosmIbcTokenAdapter['properties'] & {
+ derivedIbcDenom: string;
+ intermediateChainName: ChainName;
+ },
+ ) {
+ super(chainName, multiProvider, addresses, properties);
+ }
+
+ async populateTransferRemoteTx(
+ transferParams: TransferRemoteParams,
+ ): Promise {
+ const cwAdapter = new CwHypCollateralAdapter(
+ this.properties.intermediateChainName,
+ this.multiProvider,
+ {
+ token: this.properties.derivedIbcDenom,
+ warpRouter: this.addresses.intermediateRouterAddress,
+ },
+ this.properties.derivedIbcDenom,
+ );
+ const transfer = await cwAdapter.populateTransferRemoteTx(transferParams);
+ const cwMemo = {
+ wasm: {
+ contract: transfer.contractAddress,
+ msg: transfer.msg,
+ funds: transfer.funds,
+ },
};
+ const memo = JSON.stringify(cwMemo);
+ if (transfer.funds?.length !== 1) {
+ // Only transfers where the interchain gas denom matches the token are currently supported
+ throw new Error('Expected exactly one denom for IBC to Warp transfer');
+ }
+ // Grab amount from the funds details which accounts for interchain gas
+ const weiAmountOrId = transfer.funds[0].amount;
+ return super.populateTransferRemoteTx(
+ {
+ ...transferParams,
+ weiAmountOrId,
+ recipient: this.addresses.intermediateRouterAddress,
+ },
+ memo,
+ );
}
}
diff --git a/typescript/utils/package.json b/typescript/utils/package.json
index f2ce16c190..a9904075eb 100644
--- a/typescript/utils/package.json
+++ b/typescript/utils/package.json
@@ -1,7 +1,7 @@
{
"name": "@hyperlane-xyz/utils",
"description": "General utilities and types for the Hyperlane network",
- "version": "3.1.0-beta0",
+ "version": "3.1.0-beta3",
"dependencies": {
"@cosmjs/encoding": "^0.31.3",
"@solana/web3.js": "^1.78.0",
diff --git a/yarn.lock b/yarn.lock
index b2444c031c..87f5743fe6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4097,12 +4097,12 @@ __metadata:
languageName: node
linkType: hard
-"@hyperlane-xyz/core@3.1.0-beta0, @hyperlane-xyz/core@workspace:solidity":
+"@hyperlane-xyz/core@3.1.0-beta3, @hyperlane-xyz/core@workspace:solidity":
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/core@workspace:solidity"
dependencies:
"@eth-optimism/contracts": ^0.6.0
- "@hyperlane-xyz/utils": 3.1.0-beta0
+ "@hyperlane-xyz/utils": 3.1.0-beta3
"@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-waffle": ^2.0.3
"@openzeppelin/contracts": ^4.8.0
@@ -4125,12 +4125,12 @@ __metadata:
languageName: unknown
linkType: soft
-"@hyperlane-xyz/helloworld@3.1.0-beta0, @hyperlane-xyz/helloworld@workspace:typescript/helloworld":
+"@hyperlane-xyz/helloworld@3.1.0-beta3, @hyperlane-xyz/helloworld@workspace:typescript/helloworld":
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/helloworld@workspace:typescript/helloworld"
dependencies:
- "@hyperlane-xyz/core": 3.1.0-beta0
- "@hyperlane-xyz/sdk": 3.1.0-beta0
+ "@hyperlane-xyz/core": 3.1.0-beta3
+ "@hyperlane-xyz/sdk": 3.1.0-beta3
"@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-waffle": ^2.0.3
"@openzeppelin/contracts-upgradeable": ^4.8.0
@@ -4170,9 +4170,9 @@ __metadata:
"@ethersproject/experimental": ^5.7.0
"@ethersproject/hardware-wallets": ^5.7.0
"@ethersproject/providers": ^5.7.2
- "@hyperlane-xyz/helloworld": 3.1.0-beta0
- "@hyperlane-xyz/sdk": 3.1.0-beta0
- "@hyperlane-xyz/utils": 3.1.0-beta0
+ "@hyperlane-xyz/helloworld": 3.1.0-beta3
+ "@hyperlane-xyz/sdk": 3.1.0-beta3
+ "@hyperlane-xyz/utils": 3.1.0-beta3
"@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-etherscan": ^3.0.3
"@nomiclabs/hardhat-waffle": ^2.0.3
@@ -4216,14 +4216,14 @@ __metadata:
languageName: unknown
linkType: soft
-"@hyperlane-xyz/sdk@3.1.0-beta0, @hyperlane-xyz/sdk@workspace:typescript/sdk":
+"@hyperlane-xyz/sdk@3.1.0-beta3, @hyperlane-xyz/sdk@workspace:typescript/sdk":
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/sdk@workspace:typescript/sdk"
dependencies:
"@cosmjs/cosmwasm-stargate": ^0.31.3
"@cosmjs/stargate": ^0.31.3
- "@hyperlane-xyz/core": 3.1.0-beta0
- "@hyperlane-xyz/utils": 3.1.0-beta0
+ "@hyperlane-xyz/core": 3.1.0-beta3
+ "@hyperlane-xyz/utils": 3.1.0-beta3
"@nomiclabs/hardhat-ethers": ^2.2.1
"@nomiclabs/hardhat-waffle": ^2.0.3
"@solana/spl-token": ^0.3.8
@@ -4233,6 +4233,7 @@ __metadata:
"@types/node": ^16.9.1
"@types/ws": ^8.5.5
"@wagmi/chains": ^0.2.6
+ bignumber.js: ^9.1.1
chai: ^4.3.6
coingecko-api: ^1.0.10
cosmjs-types: ^0.9.0
@@ -4253,7 +4254,7 @@ __metadata:
languageName: unknown
linkType: soft
-"@hyperlane-xyz/utils@3.1.0-beta0, @hyperlane-xyz/utils@workspace:typescript/utils":
+"@hyperlane-xyz/utils@3.1.0-beta3, @hyperlane-xyz/utils@workspace:typescript/utils":
version: 0.0.0-use.local
resolution: "@hyperlane-xyz/utils@workspace:typescript/utils"
dependencies: