Skip to content

Commit

Permalink
feat: support Cosmos Snap for Metamask
Browse files Browse the repository at this point in the history
  • Loading branch information
mikasackermn committed Nov 29, 2023
1 parent 660c2ba commit 97fa94c
Show file tree
Hide file tree
Showing 17 changed files with 632 additions and 39 deletions.
3 changes: 1 addition & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module",
// "project": ["tsconfig.base.json"]
"project": true
"project": ["tsconfig.base.json"]
},
"rules": {
"no-extra-boolean-cast": "off",
Expand Down
58 changes: 58 additions & 0 deletions signers/signer-cosmos-snap/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# [0.14.0](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.14.0) (2023-08-03)



# [0.13.0](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.13.0) (2023-08-01)



# [0.9.0](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.9.0) (2023-07-31)


### Features

* Support for WalletConnect 2 ([faedef0](https://github.com/rango-exchange/rango-client/commit/faedef0b5e6fc3c5ef881cbbe4ec05334cc1c910))
* support safe wallet ([d04cbcd](https://github.com/rango-exchange/rango-client/commit/d04cbcd2a612755563512d9dff6f2312088d8b4d))



# [0.7.0](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.7.0) (2023-07-11)



# [0.6.0](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.6.0) (2023-07-11)


### Bug Fixes

* better parsing of evm rpc errors ([f23031a](https://github.com/rango-exchange/rango-client/commit/f23031ae14e6e841ee488591bd1bf58cfa7ca15b))
* fix signer wait change network issues ([e453db6](https://github.com/rango-exchange/rango-client/commit/e453db6ccf7736e36e5ada0c29502be32254fe9c))
* show tenderly error on call exception ([c218f49](https://github.com/rango-exchange/rango-client/commit/c218f49f3330706d9262b0cf3ec8e293e91e3729))



# [0.5.0](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.5.0) (2023-05-31)



# [0.4.0](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.4.0) (2023-05-31)



# [0.3.0](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.3.0) (2023-05-30)



# [0.2.0](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.2.0) (2023-05-30)



## [0.1.13](https://github.com/rango-exchange/rango-client/compare/[email protected]@0.1.13) (2023-05-15)


### Bug Fixes

* update rango-types and fix notification bugs ([993f185](https://github.com/rango-exchange/rango-client/commit/993f185e0b8c5e5e15a2c65ba2d85d1f9c8daa90))



35 changes: 35 additions & 0 deletions signers/signer-cosmos-snap/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@rango-dev/signer-cosmos-snap",
"version": "0.17.0",
"license": "MIT",
"type": "module",
"module": "./dist/index.js",
"main": "./dist/index.js",
"exports": {
".": "./dist/index.js"
},
"typings": "dist/index.d.ts",
"files": [
"dist",
"src"
],
"scripts": {
"build": "node ../../scripts/build/command.mjs --path signers/signer-cosmos-snap",
"clean": "rimraf dist",
"format": "prettier --write '{.,src}/**/*.{ts,tsx}'",
"lint": "eslint \"**/*.{ts,tsx}\" --ignore-path ../../.eslintignore",
"test": "vitest",
"test:watch": "vitest --watch",
"test:coverage": "vitest run --coverage"
},
"dependencies": {
"rango-types": "^0.1.46",
"@cosmjs/amino": "^0.31.3",
"@cosmjs/proto-signing": "^0.30.1",
"@cosmjs/stargate": "^0.31.1",
"@rango-dev/signer-cosmos": "^0.17.0"
},
"publishConfig": {
"access": "public"
}
}
1 change: 1 addition & 0 deletions signers/signer-cosmos-snap/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# @rango-dev/signer-evm
157 changes: 157 additions & 0 deletions signers/signer-cosmos-snap/src/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import type { AminoSignResponse, StdSignDoc } from '@cosmjs/amino';
import type { DirectSignResponse } from '@cosmjs/proto-signing';
import type { DeliverTxResponse } from '@cosmjs/stargate';
import type { CosmosTransaction } from 'rango-types';

import { makeSignDoc } from '@cosmjs/amino';
import { getSignedTx } from '@rango-dev/signer-cosmos';
import { SignerError, SignerErrorCode } from 'rango-types';

export const DEFAULT_SNAP_ID = 'npm:@cosmsnap/snap';

const signAmino = async (
chain_id: string,
signer: string,
sign_doc: StdSignDoc,
provider: any
): Promise<AminoSignResponse> => {
const result = await provider.request({
method: 'wallet_invokeSnap',
params: {
snapId: DEFAULT_SNAP_ID,
request: {
method: 'signAmino',
params: {
chain_id,
sign_doc,
signer,
},
},
},
});
return result.data;
};

interface SnapResponse<T> {
data: T;
success: boolean;
statusCode: number;
}

export const signDirect = async (
chain_id: string,
signer: string,
sign_doc: {
bodyBytes?: Uint8Array | null;
authInfoBytes?: Uint8Array | null;
chainId?: string | null;
accountNumber?: Long | null;
},
provider: any
): Promise<DirectSignResponse> => {
const result: SnapResponse<DirectSignResponse> = await provider.request({
method: 'wallet_invokeSnap',
params: {
snapId: DEFAULT_SNAP_ID,
request: {
method: 'signDirect',
params: {
chain_id,
sign_doc,
signer,
},
},
},
});
return result.data;
};

const sendTx = async (
chain_id: string,
tx: Uint8Array,
provider: any
): Promise<DeliverTxResponse> => {
const result = await provider.request({
method: 'wallet_invokeSnap',
params: {
snapId: DEFAULT_SNAP_ID,
request: {
method: 'sendTx',
params: {
chain_id,
tx: JSON.stringify(tx),
},
},
},
});
return result.data;
};

export const executeTransaction = async (
cosmosTx: CosmosTransaction,
provider: any
): Promise<string> => {
if (!provider) {
throw SignerError.AssertionFailed('wallet is null!');
}
try {
const { sequence, account_number, chainId, msgs, fee, memo, signType } =
cosmosTx.data;
const msgsWithoutType = msgs.map((m) => ({
...m,
__type: undefined,
'@type': undefined,
}));
if (!chainId) {
throw SignerError.AssertionFailed('chainId is undefined from server');
}
if (!account_number) {
throw SignerError.AssertionFailed(
'account_number is undefined from server'
);
}
if (!sequence) {
throw SignerError.AssertionFailed('sequence is undefined from server');
}
if (signType === 'AMINO') {
const signDoc = makeSignDoc(
msgsWithoutType as any,
fee as any,
chainId,
memo || undefined,
account_number,
sequence
);

let signResponse;
try {
signResponse = await signAmino(
chainId,
cosmosTx.fromWalletAddress,
signDoc,
provider
);
} catch (err) {
throw new SignerError(SignerErrorCode.SIGN_TX_ERROR, undefined, err);
}
const signedTx = getSignedTx(cosmosTx, signResponse);

const result = await sendTx(chainId, signedTx, provider);
console.log({ result });
} else if (signType === 'DIRECT') {
console.log('Direct');
}

throw new SignerError(
SignerErrorCode.OPERATION_UNSUPPORTED,
`Sign type for cosmos not supported, type: ${signType}`
);
} catch (err) {
console.log({ err });
if (SignerError.isSignerError(err)) {
throw err;
} else {
throw new SignerError(SignerErrorCode.SEND_TX_ERROR, undefined, err);
}
}
};
1 change: 1 addition & 0 deletions signers/signer-cosmos-snap/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { DefaultCosmosSnapSigner } from './signer';
43 changes: 43 additions & 0 deletions signers/signer-cosmos-snap/src/signer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */

import type { GenericSigner } from 'rango-types';
import type { CosmosTransaction } from 'rango-types/lib/api/main';

import { DEFAULT_SNAP_ID, executeTransaction } from './helper';

export class DefaultCosmosSnapSigner
implements GenericSigner<CosmosTransaction>
{
private provider: any;
constructor(provider: any) {
this.provider = provider;
}
async signMessage(
msg: string,
_address: string,
chainId: string | null
): Promise<string> {
if (!chainId) {
throw Error('ChainId is required');
}
const result = await this.provider.request({
method: 'wallet_invokeSnap',
params: {
snapId: DEFAULT_SNAP_ID,
request: {
method: 'txAlert',
params: {
chain_id: chainId,
hash: msg,
},
},
},
});
return result.data;
}

async signAndSendTx(tx: CosmosTransaction): Promise<{ hash: string }> {
const hash = await executeTransaction(tx, this.provider);
return { hash };
}
}
11 changes: 11 additions & 0 deletions signers/signer-cosmos-snap/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
// see https://www.typescriptlang.org/tsconfig to better understand tsconfigs
"extends": "../../tsconfig.lib.json",
"include": ["src", "types"],
"compilerOptions": {
"outDir": "dist",
"rootDir": "./src",
"lib": ["dom", "esnext"]
// match output dir to input dir. e.g. dist/index instead of dist/src/index
}
}
4 changes: 2 additions & 2 deletions signers/signer-cosmos/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const executeCosmosTransaction = async (
} catch (err) {
throw new SignerError(SignerErrorCode.SIGN_TX_ERROR, undefined, err);
}
const signedTx = getsignedTx(cosmosTx, signResponse);
const signedTx = getSignedTx(cosmosTx, signResponse);
const result = await cosmosProvider.sendTx(
chainId,
signedTx,
Expand Down Expand Up @@ -133,7 +133,7 @@ export const executeCosmosTransaction = async (
}
};

export function getsignedTx(
export function getSignedTx(
cosmosTx: CosmosTransaction,
signResponse: AminoSignResponse
) {
Expand Down
2 changes: 1 addition & 1 deletion signers/signer-cosmos/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { DefaultCosmosSigner } from './signer';
export { executeCosmosTransaction, getsignedTx } from './helpers';
export { executeCosmosTransaction, getSignedTx } from './helpers';
8 changes: 4 additions & 4 deletions wallets/provider-metamask/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ export function metamask() {
if (isCoinbaseWalletAvailable) {
// Getting intance from overrided structure from coinbase.
return getCoinbaseInstance('metamask');
} else {
if (!!ethereum && ethereum.isMetaMask) {
return ethereum;
}
}
if (!!ethereum && ethereum.isMetaMask) {
return ethereum;
}

return null;
}
Loading

0 comments on commit 97fa94c

Please sign in to comment.