Skip to content

Commit

Permalink
update typescript abi (#3475)
Browse files Browse the repository at this point in the history
- **fix(typescript-sdk): update ucs-03.ts**
- **fix(typescript-sdk): update transfer abi args**
  • Loading branch information
cor authored Jan 9, 2025
2 parents 0fd2489 + cc19225 commit 7ec0a4a
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 112 deletions.
31 changes: 15 additions & 16 deletions typescript-sdk/src/abi/ucs-03.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,28 +50,28 @@ export const ucs03ZkgmAbi = [
},
{
type: "function",
name: "SYSCALL_BATCH",
name: "OP_BATCH",
inputs: [],
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
stateMutability: "view"
},
{
type: "function",
name: "SYSCALL_FORWARD",
name: "OP_FORWARD",
inputs: [],
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
stateMutability: "view"
},
{
type: "function",
name: "SYSCALL_FUNGIBLE_ASSET_TRANSFER",
name: "OP_FUNGIBLE_ASSET_TRANSFER",
inputs: [],
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
stateMutability: "view"
},
{
type: "function",
name: "SYSCALL_MULTIPLEX",
name: "OP_MULTIPLEX",
inputs: [],
outputs: [{ name: "", type: "uint8", internalType: "uint8" }],
stateMutability: "view"
Expand Down Expand Up @@ -291,7 +291,7 @@ export const ucs03ZkgmAbi = [
name: "onRecvPacket",
inputs: [
{
name: "packet",
name: "operand",
type: "tuple",
internalType: "struct IBCPacket",
components: [
Expand Down Expand Up @@ -380,13 +380,13 @@ export const ucs03ZkgmAbi = [
{ name: "timeoutTimestamp", type: "uint64", internalType: "uint64" },
{ name: "salt", type: "bytes32", internalType: "bytes32" },
{
name: "syscallPacket",
name: "instruction",
type: "tuple",
internalType: "struct SyscallPacket",
internalType: "struct Instruction",
components: [
{ name: "version", type: "uint8", internalType: "uint8" },
{ name: "index", type: "uint8", internalType: "uint8" },
{ name: "packet", type: "bytes", internalType: "bytes" }
{ name: "opcode", type: "uint8", internalType: "uint8" },
{ name: "operand", type: "bytes", internalType: "bytes" }
]
}
],
Expand All @@ -405,15 +405,14 @@ export const ucs03ZkgmAbi = [
name: "transfer",
inputs: [
{ name: "channelId", type: "uint32", internalType: "uint32" },
{ name: "receiver", type: "bytes", internalType: "bytes" },
{ name: "baseToken", type: "address", internalType: "address" },
{ name: "baseAmount", type: "uint256", internalType: "uint256" },
{ name: "quoteToken", type: "bytes", internalType: "bytes" },
{ name: "quoteAmount", type: "uint256", internalType: "uint256" },
{ name: "timeoutHeight", type: "uint64", internalType: "uint64" },
{ name: "timeoutTimestamp", type: "uint64", internalType: "uint64" },
{ name: "salt", type: "bytes32", internalType: "bytes32" },
{ name: "receiver", type: "bytes", internalType: "bytes" },
{ name: "sentToken", type: "address", internalType: "address" },
{ name: "sentAmount", type: "uint256", internalType: "uint256" },
{ name: "askToken", type: "bytes", internalType: "bytes" },
{ name: "askAmount", type: "uint256", internalType: "uint256" },
{ name: "onlyMaker", type: "bool", internalType: "bool" }
{ name: "salt", type: "bytes32", internalType: "bytes32" }
],
outputs: [],
stateMutability: "nonpayable"
Expand Down
66 changes: 26 additions & 40 deletions typescript-sdk/src/evm/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,30 +65,18 @@ export const createEvmClient = (parameters: EvmClientParameters) => {
.extend(publicActions)
.extend(client => ({
transferAsset: async ({
memo,
amount,
account,
receiver,
denomAddress,
simulate = true,
destinationChainId,
autoApprove = false,
relayContractAddress
autoApprove = false
}: TransferAssetsParameters<EvmChainId>): Promise<Result<Hex, Error>> => {
account ||= client.account
console.log(`EVM client created for chainId: ${parameters.chainId}`)
// first check if chain ids are the same, if yes then we can skip the hubble check and do a simple erc20 transfer
// if (parameters.chainId === destinationChainId) {
// const transfer = await evmSameChainTransfer(client, {
// amount,
// account,
// simulate,
// receiver,
// denomAddress
// })
// if (transfer.isErr()) return err(transfer.error)
// return ok(transfer.value)
// }

const baseToken = denomAddress

const chainDetails = await getHubbleChainDetails({
sourceChainId: parameters.chainId,
Expand All @@ -105,43 +93,41 @@ export const createEvmClient = (parameters: EvmClientParameters) => {

// We need to predict the askToken denom based on the sentToken (denomAddress in the transferAssetFromEvm args)
// we do this by calling the ucs03 instance on the counterparty chain.
const [askToken, _] = (await destinationChainClient.readContract({
const [quoteToken, _] = (await destinationChainClient.readContract({
address: chainDetails.value.destinationUCS03Address as `0x${string}`,
abi: ucs03ZkgmAbi,
functionName: "predictWrappedToken",
args: [0, chainDetails.value.destinationChannel, denomAddress]
args: [0, chainDetails.value.destinationChannel, baseToken]
})) as ["0x${string}", string]

console.log({ sentToken: denomAddress, askToken }) // useful for debugging app

// if (chainDetails.value.transferType === "pfm") {
// if (!chainDetails.value.port) return err(new Error("Port not found in hubble"))
// const pfmMemo = createPfmMemo({
// channel: chainDetails.value.destinationChannel,
// port: chainDetails.value.port,
// receiver: cosmosChainId.includes(destinationChainId)
// ? bech32AddressToHex({ address: receiver })
// : receiver
// })

// if (pfmMemo.isErr()) return err(pfmMemo.error)
// memo = pfmMemo.value
// }

const sourceChannel = chainDetails.value.sourceChannel
relayContractAddress ??= getAddress(chainDetails.value.relayContractAddress)
const ucs03address = getAddress(chainDetails.value.relayContractAddress)

if (autoApprove) {
const approveResponse = await evmApproveTransferAsset(client, {
amount,
account,
denomAddress: baseToken,
receiver: ucs03address
})
if (approveResponse.isErr()) {
return approveResponse
}
console.log("approval", approveResponse.value)
}

console.log({ sourceChannel, ucs03address, baseToken, quoteToken, amount }) // useful for debugging app

return await transferAssetFromEvm(client, {
memo,
amount,
baseToken,
baseAmount: amount,
account,
simulate,
receiver,
autoApprove,
denomAddress,
askToken,
quoteToken,
quoteAmount: amount,
sourceChannel,
relayContractAddress
ucs03address
})
},
approveTransaction: async ({
Expand Down
98 changes: 42 additions & 56 deletions typescript-sdk/src/evm/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,15 @@ import {
} from "viem"

export type EvmTransferParams = {
memo?: string
askToken: HexAddress
amount: bigint
sourceChannel: number
receiver: string
baseToken: HexAddress
baseAmount: bigint
quoteToken: HexAddress
quoteAmount: bigint
account?: Account
simulate?: boolean
autoApprove?: boolean
sourceChannel: number
denomAddress: HexAddress
relayContractAddress: HexAddress
ucs03address: HexAddress
}

/**
Expand All @@ -44,78 +43,62 @@ export type EvmTransferParams = {
export async function transferAssetFromEvm(
client: WalletClient & PublicActions,
{
memo,
amount,
account,
receiver,
denomAddress,
askToken,
baseToken,
baseAmount,
quoteToken,
quoteAmount,
sourceChannel,
simulate = true,
autoApprove = false,
relayContractAddress
ucs03address
}: EvmTransferParams
): Promise<Result<Hex, Error>> {
account ||= client.account
if (!account) return err(new Error("No account found"))

denomAddress = getAddress(denomAddress)
/* lowercasing because for some reason our ucs01 contract only likes lowercase address */
relayContractAddress = getAddress(relayContractAddress).toLowerCase() as HexAddress

if (autoApprove) {
const approveResponse = await evmApproveTransferAsset(client, {
amount,
account,
denomAddress,
receiver: relayContractAddress
})
if (approveResponse.isErr()) return approveResponse
}

memo ??= timestamp()

// add a salt to each transfer to prevent hash collisions
// important because ibc-union does not use sequence numbers
// such that intents are possible based on deterministic packet hashes
const salt = new Uint8Array(32)
crypto.getRandomValues(salt)
const rawSalt = new Uint8Array(32)
crypto.getRandomValues(rawSalt)
const salt = toHex(rawSalt)

/**
* @dev
* `UCS03` zkgm contract `transfer` function:
* - https://github.com/unionlabs/union/blob/0a08c23df0360a345cde953cb97fe4c852fade9d/evm/contracts/apps/ucs/03-zkgm/Zkgm.sol#L319
* - https://github.com/unionlabs/union/blob/0fd24893d4a1173e9c6e150c826c162871d63262/evm/contracts/apps/ucs/03-zkgm/Zkgm.sol#L301
*/
const writeContractParameters = {
account,
abi: ucs03ZkgmAbi,
chain: client.chain,
functionName: "transfer",
address: relayContractAddress,
address: ucs03address,
/**
* uint32 channelId,
* uint64 timeoutHeight,
* uint64 timeoutTimestamp,
* bytes32 salt,
* bytes calldata receiver,
* address sentToken,
* uint256 sentAmount,
* bytes calldata askToken,
* uint256 askAmount,
* bool onlyMaker
"channelId": "uint32"
"receiver": "bytes"
"baseToken": "address"
"baseAmount": "uint256"
"quoteToken": "bytes"
"quoteAmount": "uint256"
"timeoutHeight": "uint64"
"timeoutTimestamp": "uint64"
"salt": "bytes32"
*/
args: [
sourceChannel,
receiver.startsWith("0x") ? getAddress(receiver) : bech32AddressToHex({ address: receiver }),
baseToken,
baseAmount,
quoteToken,
quoteAmount,
0n, // TODO: customize timeoutheight
"0x000000000000000000000000000000000000000000000000fffffffffffffffa", // TODO: make non-hexencoded timestamp
toHex(salt),
receiver.startsWith("0x") ? getAddress(receiver) : bech32AddressToHex({ address: receiver }),
denomAddress,
amount,
askToken,
amount, // we want the same amount on dest as we send on the source
false
salt
]
} as const

if (!simulate) {
const hash = await client.writeContract(writeContractParameters)
return ok(hash)
Expand All @@ -127,10 +110,13 @@ export async function transferAssetFromEvm(
return ok(hash)
}

export type EvmApproveTransferParams = Pick<
EvmTransferParams,
"amount" | "account" | "simulate" | "denomAddress" | "receiver"
>
export type EvmApproveTransferParams = {
amount: bigint
account?: Account
receiver: HexAddress
denomAddress: HexAddress
simulate?: boolean
}

/**
* approve a transfer asset from evm
Expand Down Expand Up @@ -185,10 +171,10 @@ export async function evmApproveTransferAsset(
export async function evmSameChainTransfer(
client: WalletClient & PublicActions,
{
amount,
baseAmount: amount,
account,
receiver,
denomAddress,
baseToken: denomAddress,
simulate = true
}: Omit<EvmTransferParams, "memo" | "sourceChannel" | "relayContractAddress" | "autoApprove">
): Promise<Result<Hex, Error>> {
Expand Down

0 comments on commit 7ec0a4a

Please sign in to comment.