Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: handle ledger amino messages #215

Merged
merged 8 commits into from
Oct 25, 2023
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"ethers": "^5.7.1",
"@cosmjs/encoding": "^0.31.0",
"@cosmjs/stargate": "^0.31.0",
"@cosmjs/cosmwasm-stargate": "^0.31.0",
"cosmjs-types": "^0.8.0"
},
"resolutions": {
Expand Down
116 changes: 106 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { toUtf8 } from "@cosmjs/encoding";
import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate";
import { fromUtf8, toUtf8 } from "@cosmjs/encoding";
import {
calculateFee,
AminoMsgTransfer,
AminoTypes,
Coin,
GasPrice,
SigningStargateClient
SigningStargateClient,
calculateFee
} from "@cosmjs/stargate";
import axios, { AxiosInstance } from "axios";
import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx";
import { BigNumber, ethers, UnsignedTransaction } from "ethers";

import { BigNumber, UnsignedTransaction, ethers } from "ethers";

import {
Allowance,
Expand All @@ -34,6 +37,10 @@ import {
} from "./types";

import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
import { MsgExecuteContract } from "cosmjs-types/cosmwasm/wasm/v1/tx";
import { omitDefault } from "cosmjs-types/helpers";
import { MsgTransfer } from "cosmjs-types/ibc/applications/transfer/v1/tx";
import Long from "long";
import { parseRouteResponse } from "./0xsquid/v1/route";
import { parseSdkInfoResponse } from "./0xsquid/v1/sdk-info";
import { parseStatusResponse } from "./0xsquid/v1/status";
Expand Down Expand Up @@ -221,7 +228,7 @@ export class Squid {
}

private async validateCosmosBalance(
signer: SigningStargateClient,
signer: SigningStargateClient | SigningCosmWasmClient,
signerAddress: string,
coin: Coin
): Promise<void> {
Expand Down Expand Up @@ -314,7 +321,9 @@ export class Squid {
// handle cosmos case
if (
signer instanceof SigningStargateClient ||
signer.constructor.name === "SigningStargateClient"
signer.constructor.name === "SigningStargateClient" ||
signer instanceof SigningCosmWasmClient ||
signer.constructor.name === "SigningCosmWasmClient"
) {
return await this.executeRouteCosmos(
signer as SigningStargateClient,
Expand Down Expand Up @@ -444,13 +453,12 @@ export class Squid {
}

private async executeRouteCosmos(
signer: SigningStargateClient,
signer: SigningStargateClient | SigningCosmWasmClient,
signerAddress: string,
route: RouteData
): Promise<TxRaw> {
const cosmosMsg: CosmosMsg = JSON.parse(route.transactionRequest!.data);
const msgs = [];

switch (cosmosMsg.msgTypeUrl) {
case IBC_TRANSFER_TYPE: {
msgs.push({
Expand Down Expand Up @@ -494,9 +502,16 @@ export class Squid {
const estimatedGas = await signer.simulate(signerAddress, msgs, "");
const gasMultiplier = Number(route.transactionRequest!.maxFeePerGas) || 1.3;

// This conversion is needed for Ledger, They only supports Amino messages
// TODO: At the moment there's a limit on Ledger Nano S models
// This limit prevents WASM_TYPE messages to be signed (because payload message is too big)
const converter = this.getAminoTypeConverters();
const aminoMsg = converter.toAmino(msgs[0]);
const fromAminoMsg = converter.fromAmino(aminoMsg);

return signer.sign(
signerAddress,
msgs,
[fromAminoMsg],
calculateFee(
Math.trunc(estimatedGas * gasMultiplier),
GasPrice.fromString(route.transactionRequest!.gasPrice)
Expand Down Expand Up @@ -730,6 +745,87 @@ export class Squid {

return response.data.price;
}

// TODO: There's probably a way to get this conversion from an existing library
private getAminoTypeConverters(): AminoTypes {
return new AminoTypes({
[WASM_TYPE]: {
aminoType: "wasm/MsgExecuteContract",
toAmino: ({ sender, contract, msg, funds }: MsgExecuteContract) => ({
sender: sender,
contract: contract,
msg: JSON.parse(fromUtf8(msg)),
funds: funds
}),
fromAmino: ({ sender, contract, msg, funds }): MsgExecuteContract => ({
sender: sender,
contract: contract,
msg: toUtf8(JSON.stringify(msg)),
funds: [...funds]
})
},
[IBC_TRANSFER_TYPE]: {
aminoType: "cosmos-sdk/MsgTransfer",
toAmino: ({
sourcePort,
sourceChannel,
token,
sender,
receiver,
timeoutHeight,
timeoutTimestamp,
memo
}: MsgTransfer) => ({
source_port: sourcePort,
source_channel: sourceChannel,
token: token,
sender: sender,
receiver: receiver,
timeout_height: timeoutHeight
? {
revision_height: omitDefault(
timeoutHeight.revisionHeight
)?.toString(),
revision_number: omitDefault(
timeoutHeight.revisionNumber
)?.toString()
}
: {},
timeout_timestamp: omitDefault(timeoutTimestamp)?.toString(),
memo: omitDefault(memo)?.toString()
}),
fromAmino: ({
source_port,
source_channel,
token,
sender,
receiver,
timeout_height,
timeout_timestamp
odcey marked this conversation as resolved.
Show resolved Hide resolved
}: AminoMsgTransfer["value"]): MsgTransfer =>
MsgTransfer.fromPartial({
sourcePort: source_port,
sourceChannel: source_channel,
token: token,
sender: sender,
receiver: receiver,
timeoutHeight: timeout_height
? {
revisionHeight: Long.fromString(
timeout_height.revision_height || "0",
true
),
revisionNumber: Long.fromString(
timeout_height.revision_number || "0",
true
)
}
: undefined,
timeoutTimestamp: Long.fromString(timeout_timestamp || "0", true)
})
}
});
}
}

export * from "./types";
24 changes: 23 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1013,6 +1013,23 @@
"@cosmjs/math" "^0.31.1"
"@cosmjs/utils" "^0.31.1"

"@cosmjs/cosmwasm-stargate@^0.31.0":
version "0.31.1"
resolved "https://registry.yarnpkg.com/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.31.1.tgz#36d4386238fd4310d144486a27585a4fec3f27cd"
integrity sha512-5hwv4oztFnpqnFaXhYxZc93na3qdxylT2kqms4pLzD8CWMEQmrwhdM4KpZimrsyZK55WiMQtTPsdSh7M8KLOow==
dependencies:
"@cosmjs/amino" "^0.31.1"
"@cosmjs/crypto" "^0.31.1"
"@cosmjs/encoding" "^0.31.1"
"@cosmjs/math" "^0.31.1"
"@cosmjs/proto-signing" "^0.31.1"
"@cosmjs/stargate" "^0.31.1"
"@cosmjs/tendermint-rpc" "^0.31.1"
"@cosmjs/utils" "^0.31.1"
cosmjs-types "^0.8.0"
long "^4.0.0"
pako "^2.0.2"

"@cosmjs/crypto@^0.31.1":
version "0.31.1"
resolved "https://registry.yarnpkg.com/@cosmjs/crypto/-/crypto-0.31.1.tgz#ce4917df0f7b38f0909a32020907ccff04acefe6"
Expand Down Expand Up @@ -1073,7 +1090,7 @@
ws "^7"
xstream "^11.14.0"

"@cosmjs/stargate@^0.31.0":
"@cosmjs/stargate@^0.31.0", "@cosmjs/stargate@^0.31.1":
version "0.31.1"
resolved "https://registry.yarnpkg.com/@cosmjs/stargate/-/stargate-0.31.1.tgz#7e2b0fd6f181250915b1d73ecf9dfbab6f3cdd0d"
integrity sha512-TqOJZYOH5W3sZIjR6949GfjhGXO3kSHQ3/KmE+SuKyMMmQ5fFZ45beawiRtVF0/CJg5RyPFyFGJKhb1Xxv3Lcg==
Expand Down Expand Up @@ -5859,6 +5876,11 @@ package-json@^8.1.0:
registry-url "^6.0.0"
semver "^7.3.7"

pako@^2.0.2:
version "2.1.0"
resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86"
integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==

parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
Expand Down