@mictonode/widget 0.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/.github/FUNDING.yml +3 -0
  2. package/.github/workflows/npm-publish.yml +34 -0
  3. package/.prettierrc.json +9 -0
  4. package/.vscode/extensions.json +3 -0
  5. package/README.md +41 -0
  6. package/dist/main-172a6585.js +404361 -0
  7. package/dist/ping-widget.js +13 -0
  8. package/dist/ping-widget.umd.cjs +96 -0
  9. package/dist/query.lcd-2adf1c0c.js +129 -0
  10. package/dist/query.rpc.Query-b53908e7.js +2316 -0
  11. package/dist/tx.rpc.msg-d234ff40.js +37 -0
  12. package/dist/tx.rpc.msg-f7a80a78.js +21 -0
  13. package/example/.vscode/extensions.json +3 -0
  14. package/example/README.md +7 -0
  15. package/example/index.html +12 -0
  16. package/example/package.json +19 -0
  17. package/example/pnpm-lock.yaml +465 -0
  18. package/example/public/cdn.html +19 -0
  19. package/example/src/App.vue +73 -0
  20. package/example/src/main.js +4 -0
  21. package/example/vite.config.js +7 -0
  22. package/index.html +12 -0
  23. package/lib/components/ConnectWallet/index.vue +267 -0
  24. package/lib/components/TokenConvert/index.vue +1033 -0
  25. package/lib/components/TokenConvert/tokens.ts +37 -0
  26. package/lib/components/TxDialog/index.vue +432 -0
  27. package/lib/components/TxDialog/messages/Delegate.vue +194 -0
  28. package/lib/components/TxDialog/messages/Deposit.vue +97 -0
  29. package/lib/components/TxDialog/messages/MsgDelegate.ts +0 -0
  30. package/lib/components/TxDialog/messages/Redelegate.vue +189 -0
  31. package/lib/components/TxDialog/messages/Send.vue +142 -0
  32. package/lib/components/TxDialog/messages/Transfer.vue +248 -0
  33. package/lib/components/TxDialog/messages/Unbond.vue +137 -0
  34. package/lib/components/TxDialog/messages/Vote.vue +63 -0
  35. package/lib/components/TxDialog/messages/Withdraw.vue +56 -0
  36. package/lib/components/TxDialog/messages/WithdrawCommission.vue +75 -0
  37. package/lib/components/TxDialog/wasm/ClearAdmin.vue +56 -0
  38. package/lib/components/TxDialog/wasm/ExecuteContract.vue +99 -0
  39. package/lib/components/TxDialog/wasm/InstantiateContract.vue +109 -0
  40. package/lib/components/TxDialog/wasm/MigrateContract.vue +77 -0
  41. package/lib/components/TxDialog/wasm/MigrateContract2.vue +77 -0
  42. package/lib/components/TxDialog/wasm/StoreCode.vue +101 -0
  43. package/lib/components/TxDialog/wasm/UpdateAdmin.vue +75 -0
  44. package/lib/main.css +7 -0
  45. package/lib/main.ts +23 -0
  46. package/lib/utils/TokenUnitConverter.ts +45 -0
  47. package/lib/utils/format.ts +16 -0
  48. package/lib/utils/http.ts +223 -0
  49. package/lib/utils/type.ts +77 -0
  50. package/lib/wallet/EthermintMessageAdapter.ts +136 -0
  51. package/lib/wallet/UniClient.ts +152 -0
  52. package/lib/wallet/Wallet.ts +138 -0
  53. package/lib/wallet/wallets/InitiaWallet.ts +189 -0
  54. package/lib/wallet/wallets/KeplerWallet.ts +158 -0
  55. package/lib/wallet/wallets/LeapWallet.ts +142 -0
  56. package/lib/wallet/wallets/LedgerWallet.ts +203 -0
  57. package/lib/wallet/wallets/MetamaskSnapWallet.ts +105 -0
  58. package/lib/wallet/wallets/MetamaskWallet.ts +173 -0
  59. package/lib/wallet/wallets/OKXWallet.ts +202 -0
  60. package/lib/wallet/wallets/UnisatWallet.ts +198 -0
  61. package/package.json +102 -0
  62. package/postcss.config.js +6 -0
  63. package/src/App.vue +241 -0
  64. package/src/main.ts +4 -0
  65. package/src/vite-env.d.ts +1 -0
  66. package/tailwind.config.js +34 -0
  67. package/tsconfig.json +25 -0
  68. package/tsconfig.node.json +10 -0
  69. package/vite.config.ts +62 -0
  70. package/vue-shim.d.ts +6 -0
@@ -0,0 +1,158 @@
1
+ import { fromBase64, fromBech32, toHex } from "@cosmjs/encoding";
2
+ import { Registry, TxBodyEncodeObject, encodePubkey, makeAuthInfoBytes, makeSignDoc} from "@cosmjs/proto-signing"
3
+ import { AbstractWallet, Account, WalletArgument, WalletName, keyType } from "../Wallet"
4
+ import { Transaction } from "../../utils/type"
5
+ //import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
6
+ import { TxRaw } from "@initia/initia.proto/cosmos/tx/v1beta1/tx";
7
+ import { Any } from "cosmjs-types/google/protobuf/any";
8
+ import { PubKey } from 'cosmjs-types/cosmos/crypto/secp256k1/keys'
9
+ import { SignMode } from "cosmjs-types/cosmos/tx/signing/v1beta1/signing";
10
+
11
+ //import { AminoTypes, createDefaultAminoConverters } from "@cosmjs/stargate";
12
+ import { encodeSecp256k1Pubkey, makeSignDoc as makeSignDocAmino } from "@cosmjs/amino";
13
+ import { createWasmAminoConverters } from "@cosmjs/cosmwasm-stargate";
14
+
15
+ import { SignDoc } from "@initia/initia.js";
16
+
17
+ import { TimeoutError, createAminoTypes, createRegistry, defined, getRPC } from "@initia/utils"
18
+
19
+
20
+
21
+
22
+ export class KeplerWallet implements AbstractWallet {
23
+ aminoTypes: any;
24
+ name: WalletName.Keplr
25
+ chainId: string
26
+ registry: Registry
27
+ conf: WalletArgument
28
+ createAminoConverters = createAminoTypes()
29
+ constructor(arg: WalletArgument, registry: Registry) {
30
+ this.chainId = arg.chainId || "initia"
31
+ this.aminoTypes = createAminoTypes();
32
+ // @ts-ignore
33
+ if (!window.getOfflineSigner || !window.keplr) {
34
+ throw new Error('Please install keplr extension')
35
+ }
36
+ this.registry = createRegistry();
37
+ this.conf = arg;
38
+ this.name = WalletName.Keplr;
39
+ }
40
+
41
+
42
+ async getAccounts(): Promise<Account[]> {
43
+ // const chainId = 'cosmoshub'
44
+ // @ts-ignore
45
+ await window.keplr.enable(this.chainId)
46
+ // @ts-ignore
47
+ const offlineSigner = window.getOfflineSigner(this.chainId)
48
+ return offlineSigner.getAccounts()
49
+ }
50
+ supportCoinType(coinType?: string | undefined): Promise<boolean> {
51
+ return Promise.resolve(true);
52
+ }
53
+ isEthermint() {
54
+ return this.conf.hdPath && this.conf.hdPath.startsWith("m/44'/60")
55
+ }
56
+
57
+ async sign(transaction: Transaction): Promise<TxRaw> {
58
+ // sign wasm tx with signDirect
59
+ if(transaction.messages.findIndex(x => x.typeUrl.startsWith("/cosmwasm.wasm")) > -1) {
60
+ return this.signDirect(transaction);
61
+ }
62
+ return this.signAmino(transaction) ;
63
+ }
64
+ // @deprecated use signAmino instead
65
+ // because signDirect is not supported ledger wallet
66
+ async signDirect(transaction: Transaction): Promise<TxRaw> {
67
+ const accouts = await this.getAccounts()
68
+ const hex = toHex(fromBech32(transaction.signerAddress).data)
69
+ const accountFromSigner = accouts.find((account) => toHex(fromBech32(account.address).data) === hex);
70
+ if (!accountFromSigner) {
71
+ throw new Error("Failed to retrieve account from signer");
72
+ }
73
+ const pubkey = Any.fromPartial({
74
+ typeUrl: keyType(transaction.chainId),
75
+ value: PubKey.encode({
76
+ key: accountFromSigner.pubkey,
77
+ }).finish()
78
+ })
79
+ const txBodyEncodeObject: TxBodyEncodeObject = {
80
+ typeUrl: "/cosmos.tx.v1beta1.TxBody",
81
+ value: {
82
+ messages: transaction.messages,
83
+ memo: transaction.memo,
84
+ },
85
+ };
86
+
87
+ const txBodyBytes = this.registry.encode(txBodyEncodeObject);
88
+ const gasLimit = Number(transaction.fee.gas);
89
+ const authInfoBytes = makeAuthInfoBytes(
90
+ [{ pubkey, sequence: transaction.signerData.sequence }],
91
+ transaction.fee.amount,
92
+ gasLimit,
93
+ transaction.fee.granter,
94
+ transaction.fee.payer,
95
+ );
96
+ const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, transaction.chainId, transaction.signerData.accountNumber);
97
+
98
+ // @ts-ignore
99
+ const offlineSigner = window.getOfflineSigner(this.chainId)
100
+ const { signature, signed } = await offlineSigner.signDirect(transaction.signerAddress, signDoc);;
101
+ return TxRaw.fromPartial({
102
+ bodyBytes: signed.bodyBytes,
103
+ authInfoBytes: signed.authInfoBytes,
104
+ signatures: [fromBase64(signature.signature)],
105
+ });
106
+ }
107
+
108
+ async signAmino(tx: Transaction): Promise<TxRaw> {
109
+ const accounts = await this.getAccounts();
110
+ const hex = toHex(fromBech32(tx.signerAddress).data);
111
+ const accountFromSigner = accounts.find((account) => toHex(fromBech32(account.address).data) === hex);
112
+ if (!accountFromSigner) {
113
+ throw new Error("Failed to retrieve account from signer");
114
+ }
115
+
116
+ const pubkey = Any.fromPartial({
117
+ typeUrl: keyType(tx.chainId),
118
+ value: PubKey.encode({
119
+ key: accountFromSigner.pubkey,
120
+ }).finish()
121
+ });
122
+
123
+ const signMode = SignMode.SIGN_MODE_LEGACY_AMINO_JSON;
124
+ const msgs = tx.messages.map((msg) => this.aminoTypes.toAmino(msg));
125
+ const signDoc = makeSignDocAmino(msgs, tx.fee, tx.chainId, tx.memo, tx.signerData.accountNumber, tx.signerData.sequence);
126
+
127
+ // @ts-ignore
128
+ const offlineSigner = window.getOfflineSigner(this.chainId);
129
+ const { signature, signed } = await offlineSigner.signAmino(tx.signerAddress, signDoc);
130
+
131
+ const signedTxBody = {
132
+ messages: signed.msgs.map((msg: any) => this.aminoTypes.fromAmino(msg)),
133
+ memo: signed.memo,
134
+ };
135
+ const signedTxBodyEncodeObject: TxBodyEncodeObject = {
136
+ typeUrl: "/cosmos.tx.v1beta1.TxBody",
137
+ value: signedTxBody,
138
+ };
139
+ const signedTxBodyBytes = this.registry.encode(signedTxBodyEncodeObject);
140
+
141
+ const signedGasLimit = Number(signed.fee.gas);
142
+ const signedSequence = Number(signed.sequence);
143
+ const signedAuthInfoBytes = makeAuthInfoBytes(
144
+ [{ pubkey, sequence: signedSequence }],
145
+ signed.fee.amount,
146
+ signedGasLimit,
147
+ signed.fee.granter,
148
+ signed.fee.payer,
149
+ signMode,
150
+ );
151
+
152
+ return TxRaw.fromPartial({
153
+ bodyBytes: signedTxBodyBytes,
154
+ authInfoBytes: signedAuthInfoBytes,
155
+ signatures: [fromBase64(signature.signature)],
156
+ });
157
+ }
158
+ }
@@ -0,0 +1,142 @@
1
+ import { fromBase64, fromBech32, toHex } from "@cosmjs/encoding";
2
+ import { OfflineSigner, Registry, TxBodyEncodeObject, encodePubkey, makeAuthInfoBytes, makeSignDoc } from "@cosmjs/proto-signing"
3
+ import { AbstractWallet, Account, WalletArgument, WalletName, keyType } from "../Wallet"
4
+ import { Transaction } from "../../utils/type"
5
+ import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
6
+ import { Any } from "cosmjs-types/google/protobuf/any";
7
+ import { PubKey } from 'cosmjs-types/cosmos/crypto/secp256k1/keys'
8
+ import { SignMode } from "cosmjs-types/cosmos/tx/signing/v1beta1/signing";
9
+ import { AminoTypes, createDefaultAminoConverters } from "@cosmjs/stargate";
10
+ import { encodeSecp256k1Pubkey, makeSignDoc as makeSignDocAmino } from "@cosmjs/amino";
11
+ import { createWasmAminoConverters } from "@cosmjs/cosmwasm-stargate";
12
+
13
+ export class LeapWallet implements AbstractWallet {
14
+ name: WalletName.Leap
15
+ chainId: string
16
+ registry: Registry
17
+ conf: WalletArgument
18
+ signer: OfflineSigner
19
+ aminoTypes = new AminoTypes( {...createDefaultAminoConverters(), ...createWasmAminoConverters()})
20
+ constructor(arg: WalletArgument, registry: Registry) {
21
+ this.chainId = arg.chainId || "cosmoshub"
22
+ // @ts-ignore
23
+ if (!window.getOfflineSigner || !window.leap) {
24
+ throw new Error('Please install Leap extension')
25
+ }
26
+ this.registry = registry
27
+ this.conf = arg
28
+ }
29
+ async getAccounts(): Promise<Account[]> {
30
+ // const chainId = 'cosmoshub'
31
+ // @ts-ignore
32
+ await window.leap.enable(this.chainId);
33
+
34
+ // @ts-ignore
35
+ this.signer = await window.leap.getOfflineSigner(this.chainId);
36
+ const accounts = await this.signer.getAccounts();
37
+ return accounts.map(account => ({ ...account }));
38
+ }
39
+ supportCoinType(coinType?: string | undefined): Promise<boolean> {
40
+ return Promise.resolve(true);
41
+ }
42
+ isEthermint() {
43
+ return this.conf.hdPath && this.conf.hdPath.startsWith("m/44'/60")
44
+ }
45
+ async sign(transaction: Transaction): Promise<TxRaw> {
46
+ return this.signAmino(transaction)
47
+ }
48
+ // @deprecated use signAmino instead
49
+ // because signDirect is not supported ledger wallet
50
+ async signDirect(transaction: Transaction): Promise<TxRaw> {
51
+ const accouts = await this.getAccounts()
52
+ const hex = toHex(fromBech32(transaction.signerAddress).data)
53
+ const accountFromSigner = accouts.find((account) => toHex(fromBech32(account.address).data) === hex);
54
+ if (!accountFromSigner) {
55
+ throw new Error("Failed to retrieve account from signer");
56
+ }
57
+ const pubkey = Any.fromPartial({
58
+ typeUrl: keyType(transaction.chainId),
59
+ value: PubKey.encode({
60
+ key: accountFromSigner.pubkey,
61
+ }).finish()
62
+ })
63
+ const txBodyEncodeObject: TxBodyEncodeObject = {
64
+ typeUrl: "/cosmos.tx.v1beta1.TxBody",
65
+ value: {
66
+ messages: transaction.messages,
67
+ memo: transaction.memo,
68
+ },
69
+ };
70
+ const txBodyBytes = this.registry.encode(txBodyEncodeObject);
71
+ const gasLimit = Number(transaction.fee.gas);
72
+ const authInfoBytes = makeAuthInfoBytes(
73
+ [{ pubkey, sequence: transaction.signerData.sequence }],
74
+ transaction.fee.amount,
75
+ gasLimit,
76
+ transaction.fee.granter,
77
+ transaction.fee.payer,
78
+ );
79
+ const signDoc = makeSignDoc(txBodyBytes, authInfoBytes, transaction.chainId, transaction.signerData.accountNumber);
80
+
81
+ // @ts-ignore
82
+ // const offlineSigner = await window.leap.getOfflineSignerAuto(this.chainId);
83
+ // console.log(offlineSigner)
84
+ const { signature, signed } = await this.signer.signDirect(transaction.signerAddress, signDoc);;
85
+ return TxRaw.fromPartial({
86
+ bodyBytes: signed.bodyBytes,
87
+ authInfoBytes: signed.authInfoBytes,
88
+ signatures: [fromBase64(signature.signature)],
89
+ });
90
+ }
91
+
92
+ async signAmino(tx: Transaction): Promise<TxRaw> {
93
+ const accouts = await this.getAccounts()
94
+ const hex = toHex(fromBech32(tx.signerAddress).data)
95
+ const accountFromSigner = accouts.find((account) => toHex(fromBech32(account.address).data) === hex);
96
+ if (!accountFromSigner) {
97
+ throw new Error("Failed to retrieve account from signer");
98
+ }
99
+ // const pubkey = encodePubkey(encodeSecp256k1Pubkey(accountFromSigner.pubkey));
100
+ const pubkey = Any.fromPartial({
101
+ typeUrl: keyType(tx.chainId),
102
+ value: PubKey.encode({
103
+ key: accountFromSigner.pubkey,
104
+ }).finish()
105
+ })
106
+ const signMode = SignMode.SIGN_MODE_LEGACY_AMINO_JSON;
107
+ const msgs = tx.messages.map((msg) => this.aminoTypes.toAmino(msg));
108
+ const signDoc = makeSignDocAmino(msgs, tx.fee, tx.chainId, tx.memo, tx.signerData.accountNumber, tx.signerData.sequence);
109
+
110
+ // @ts-ignore
111
+ // const offlineSigner = window.getOfflineSigner(this.chainId)
112
+ const { signature, signed } = await this.signer.signAmino(tx.signerAddress, signDoc);
113
+
114
+ console.log(signature, 'signature', signed)
115
+
116
+ const signedTxBody = {
117
+ messages: signed.msgs.map((msg) => this.aminoTypes.fromAmino(msg)),
118
+ memo: signed.memo,
119
+ };
120
+ const signedTxBodyEncodeObject: TxBodyEncodeObject = {
121
+ typeUrl: "/cosmos.tx.v1beta1.TxBody",
122
+ value: signedTxBody,
123
+ };
124
+ const signedTxBodyBytes = this.registry.encode(signedTxBodyEncodeObject);
125
+
126
+ const signedGasLimit = Number(signed.fee.gas);
127
+ const signedSequence = Number(signed.sequence);
128
+ const signedAuthInfoBytes = makeAuthInfoBytes(
129
+ [{ pubkey, sequence: signedSequence }],
130
+ signed.fee.amount,
131
+ signedGasLimit,
132
+ signed.fee.granter,
133
+ signed.fee.payer,
134
+ signMode,
135
+ );
136
+ return TxRaw.fromPartial({
137
+ bodyBytes: signedTxBodyBytes,
138
+ authInfoBytes: signedAuthInfoBytes,
139
+ signatures: [fromBase64(signature.signature)],
140
+ });
141
+ }
142
+ }
@@ -0,0 +1,203 @@
1
+ import { fromBase64, fromBech32, toHex, toBech32, toBase64 } from "@cosmjs/encoding";
2
+ import { Registry, TxBodyEncodeObject, encodePubkey, makeAuthInfoBytes } from "@cosmjs/proto-signing"
3
+ import { AbstractWallet, Account, DEFAULT_HDPATH, WalletArgument, WalletName, extractChainId } from "../Wallet"
4
+ import { AminoTypes, createDefaultAminoConverters } from "@cosmjs/stargate"
5
+ import TransportWebUSB from "@ledgerhq/hw-transport-webusb"
6
+ import TransportWebBLE from "@ledgerhq/hw-transport-web-ble"
7
+ import { LedgerSigner } from "@cosmjs/ledger-amino"
8
+ import { Transaction } from "../../utils/type"
9
+ import { Chain, createTxRawEIP712, signatureToWeb3Extension } from "@tharsis/transactions";
10
+ import { createEIP712, generateFee, generateMessageWithMultipleTransactions, generateTypes } from "@tharsis/eip712";
11
+ import { defaultMessageAdapter } from "../EthermintMessageAdapter";
12
+ import { createTransactionWithMultipleMessages } from "@tharsis/proto";
13
+ import { encodeSecp256k1Pubkey, makeSignDoc as makeSignDocAmino } from "@cosmjs/amino";
14
+ import { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
15
+ import { stringToPath } from '@cosmjs/crypto'
16
+ import { SignMode } from "cosmjs-types/cosmos/tx/signing/v1beta1/signing";
17
+ import { ethermintToEth } from "../../utils/format";
18
+ import { createWasmAminoConverters } from "@cosmjs/cosmwasm-stargate";
19
+
20
+ export class LedgerWallet implements AbstractWallet {
21
+ name: WalletName.Ledger
22
+ transport: string
23
+ hdPath: string
24
+ registry: Registry
25
+ aminoTypes = new AminoTypes({...createDefaultAminoConverters(), ...createWasmAminoConverters()})
26
+ conf: WalletArgument
27
+ constructor(arg: WalletArgument, registry: Registry) {
28
+ this.transport = arg.transport || 'usb'
29
+ this.hdPath = arg.hdPath || DEFAULT_HDPATH
30
+ this.registry = registry
31
+ this.conf = arg
32
+ }
33
+
34
+ async getSigner() {
35
+ const transport = this.transport === 'usb' ? await TransportWebUSB.create() : await TransportWebBLE.create()
36
+ // extract Cointype from from HDPath
37
+ const hdPath = stringToPath(this.hdPath)
38
+ const coinType = Number(hdPath[1])
39
+ let ledgerAppName = 'Cosmos'
40
+ switch (coinType) {
41
+ case 60:
42
+ throw new Error("Not support.")
43
+ case 529:
44
+ ledgerAppName = 'Secret' // 'Secret'
45
+ break
46
+ case 852:
47
+ ledgerAppName = 'Desmos' // 'Desmos'
48
+ break
49
+ case 330:
50
+ ledgerAppName = 'Terra' // 'Terra'
51
+ break
52
+ case 118:
53
+ default:
54
+ }
55
+ // const path = stringToPath(this.hdPath)
56
+ return new LedgerSigner(transport, { ledgerAppName, hdPaths: [hdPath] })
57
+ }
58
+
59
+ async getAccounts(): Promise<Account[]> {
60
+ const signer = await this.getSigner();
61
+ const account = (await signer.getAccounts()).map(x => ({
62
+ address: x.address,
63
+ algo: x.algo,
64
+ pubkey: x.pubkey,
65
+ }))
66
+ return account
67
+ }
68
+ supportCoinType(coinType?: string | undefined): Promise<boolean> {
69
+ return Promise.resolve(true);
70
+ }
71
+ isEthermint() {
72
+ return this.conf.hdPath && this.conf.hdPath.startsWith("m/44'/60")
73
+ }
74
+
75
+ async sign(tx: Transaction): Promise<TxRaw | Uint8Array> {
76
+ // if (this.isEthermint()) {
77
+ // return this.sign712(tx)
78
+ // }
79
+ return this.signAmino(tx)
80
+ }
81
+
82
+ // not finished, due to the outdated dependency.
83
+ async sign712(tx: Transaction): Promise<Uint8Array> {
84
+ const chain: Chain = {
85
+ chainId: extractChainId(tx.signerData.chainId),
86
+ cosmosChainId: tx.chainId,
87
+ }
88
+
89
+ const signer = await this.getSigner()
90
+ const ethAddr = ethermintToEth(tx.signerAddress)
91
+
92
+ // this.signer.prefix = fromBech32(signerAddress).prefix
93
+ const account = await signer.getAccounts()
94
+
95
+ const acc = account.find(x => x.address === ethAddr)
96
+ if (!acc) {
97
+ throw new Error('The signer address dose not exsits in Ledger!')
98
+ }
99
+ const sender = {
100
+ accountAddress: tx.signerAddress,
101
+ sequence: tx.signerData.sequence,
102
+ accountNumber: tx.signerData.accountNumber,
103
+ pubkey: toBase64(account[0].pubkey),
104
+ }
105
+
106
+ const fees = generateFee(tx.fee.amount[0].amount, tx.fee.amount[0].denom, tx.fee.gas, tx.signerAddress)
107
+
108
+ const msgs = tx.messages.map(x => this.aminoTypes.toAmino(x))
109
+ const toSignTx = generateMessageWithMultipleTransactions(
110
+ sender.accountNumber.toString(),
111
+ sender.sequence.toString(),
112
+ tx.signerData.chainId,
113
+ tx.memo,
114
+ fees,
115
+ msgs,
116
+ )
117
+
118
+ const types = generateTypes(defaultMessageAdapter[tx.messages[0].typeUrl].getTypes())
119
+ const eip = createEIP712(types, chain.chainId, toSignTx)
120
+
121
+ // @ts-ignore
122
+ const sig = await this.getSigner().sign712(eip)
123
+
124
+ const rawTx = this.makeRawTxEvmos(sender, tx.messages, tx.memo, tx.fee, sig, chain)
125
+ return rawTx
126
+ }
127
+
128
+ makeRawTxEvmos(sender, messages, memo, fee, signature, chain): Uint8Array {
129
+ /// evmos style
130
+ /// *
131
+ const protoMsgs = messages.map(x => {
132
+ const adapter = defaultMessageAdapter[x.typeUrl]
133
+ return adapter.toProto(x)
134
+ })
135
+
136
+ const evmos = createTransactionWithMultipleMessages(
137
+ protoMsgs,
138
+ memo,
139
+ fee.amount[0].amount,
140
+ fee.amount[0].denom,
141
+ Number(fee.gas),
142
+ 'ethsecp256',
143
+ sender.pubkey,
144
+ sender.sequence,
145
+ sender.accountNumber,
146
+ chain.cosmosChainId,
147
+ )
148
+
149
+ const extension = signatureToWeb3Extension(chain, sender, signature)
150
+
151
+ // Create the txRaw
152
+ const prototx = createTxRawEIP712(evmos.legacyAmino.body, evmos.legacyAmino.authInfo, extension)
153
+ return prototx.message.serializeBinary()
154
+ /// end of EVMOS style */
155
+ }
156
+
157
+
158
+ async signAmino(tx: Transaction): Promise<TxRaw> {
159
+ const signer = await this.getSigner();
160
+ // assert(!isOfflineDirectSigner(signer));
161
+
162
+ const accounts = await this.getAccounts()
163
+ const {data} = fromBech32(tx.signerAddress)
164
+ const hex = toHex(data)
165
+ const signerAddress = toBech32("cosmos", data)
166
+ const accountFromSigner = accounts.find((account) => toHex(fromBech32(account.address).data) === hex);
167
+ if (!accountFromSigner) {
168
+ throw new Error("Failed to retrieve account from signer");
169
+ }
170
+ const pubkey = encodePubkey(encodeSecp256k1Pubkey(accountFromSigner.pubkey));
171
+ const signMode = SignMode.SIGN_MODE_LEGACY_AMINO_JSON;
172
+ const msgs = tx.messages.map((msg) => this.aminoTypes.toAmino(msg));
173
+ const signDoc = makeSignDocAmino(msgs, tx.fee, tx.chainId, tx.memo, tx.signerData.accountNumber, tx.signerData.sequence);
174
+ const { signature, signed } = await signer.signAmino(signerAddress, signDoc);
175
+
176
+ const signedTxBody = {
177
+ messages: signed.msgs.map((msg) => this.aminoTypes.fromAmino(msg)),
178
+ memo: signed.memo,
179
+ };
180
+ const signedTxBodyEncodeObject: TxBodyEncodeObject = {
181
+ typeUrl: "/cosmos.tx.v1beta1.TxBody",
182
+ value: signedTxBody,
183
+ };
184
+ const signedTxBodyBytes = this.registry.encode(signedTxBodyEncodeObject);
185
+
186
+ const signedGasLimit = Number(signed.fee.gas);
187
+ const signedSequence = Number(signed.sequence);
188
+ const signedAuthInfoBytes = makeAuthInfoBytes(
189
+ [{ pubkey, sequence: signedSequence }],
190
+ signed.fee.amount,
191
+ signedGasLimit,
192
+ signed.fee.granter,
193
+ signed.fee.payer,
194
+ signMode,
195
+ );
196
+ return TxRaw.fromPartial({
197
+ bodyBytes: signedTxBodyBytes,
198
+ authInfoBytes: signedAuthInfoBytes,
199
+ signatures: [fromBase64(signature.signature)],
200
+ });
201
+ }
202
+
203
+ }
@@ -0,0 +1,105 @@
1
+ import {
2
+ AbstractWallet,
3
+ Account,
4
+ WalletArgument,
5
+ WalletName,
6
+ keyType,
7
+ } from '../Wallet';
8
+ import {
9
+ fromBase64,
10
+ fromBech32,
11
+ toHex,
12
+ } from '@cosmjs/encoding';
13
+ import {
14
+ Registry,
15
+ TxBodyEncodeObject,
16
+ makeAuthInfoBytes,
17
+ makeSignDoc,
18
+ } from '@cosmjs/proto-signing';
19
+ import { Transaction } from '../../utils/type';
20
+ import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
21
+ // import { AminoTypes, createDefaultAminoConverters } from '@cosmjs/stargate';
22
+ import { Any } from 'cosmjs-types/google/protobuf/any';
23
+ import { PubKey } from 'cosmjs-types/cosmos/crypto/secp256k1/keys';
24
+
25
+ import { connectSnap, getKey, getSnap, CosmjsOfflineSigner } from '@leapwallet/cosmos-snap-provider';
26
+ // import { createWasmAminoConverters } from "@cosmjs/cosmwasm-stargate";
27
+
28
+ export class MetamaskSnapWallet implements AbstractWallet {
29
+ name: WalletName.MetamaskSnap;
30
+ chainId: string;
31
+ registry: Registry;
32
+ prefix: string;
33
+ // aminoTypes = new AminoTypes( {...createDefaultAminoConverters(), ...createWasmAminoConverters()});
34
+
35
+ constructor(arg: WalletArgument, registry: Registry) {
36
+ this.chainId = arg.chainId || 'cosmoshub';
37
+ this.registry = registry;
38
+ this.prefix = arg.prefix || 'cosmos';
39
+ }
40
+
41
+ async getAccounts(): Promise<Account[]> {
42
+ const snapInstalled = await getSnap().catch(() => {
43
+ throw new Error('Metamask snap not installed');
44
+ });
45
+ if (!snapInstalled) {
46
+ await connectSnap()
47
+ }
48
+ const key = await getKey(this.chainId)
49
+ return [key]
50
+ }
51
+
52
+ async supportCoinType(coinType?: string): Promise<boolean> {
53
+ return true;
54
+ }
55
+
56
+ async sign(transaction: Transaction): Promise<TxRaw | Uint8Array> {
57
+ const accouts = await this.getAccounts();
58
+ const hex = toHex(fromBech32(transaction.signerAddress).data);
59
+ const accountFromSigner = accouts.find(
60
+ (account) => toHex(fromBech32(account.address).data) === hex
61
+ );
62
+ if (!accountFromSigner) {
63
+ throw new Error('Failed to retrieve account from signer');
64
+ }
65
+
66
+ const pubkey = Any.fromPartial({
67
+ typeUrl: keyType(transaction.chainId),
68
+ value: PubKey.encode({
69
+ key: new Uint8Array(Object.values(accountFromSigner.pubkey)),
70
+ }).finish(),
71
+ });
72
+ const txBodyEncodeObject: TxBodyEncodeObject = {
73
+ typeUrl: '/cosmos.tx.v1beta1.TxBody',
74
+ value: {
75
+ messages: transaction.messages,
76
+ memo: transaction.memo,
77
+ },
78
+ };
79
+ const txBodyBytes = this.registry.encode(txBodyEncodeObject);
80
+ const gasLimit = Number(transaction.fee.gas);
81
+
82
+ const authInfoBytes = makeAuthInfoBytes(
83
+ [{ pubkey, sequence: transaction.signerData.sequence }],
84
+ transaction.fee.amount,
85
+ gasLimit,
86
+ transaction.fee.granter,
87
+ transaction.fee.payer
88
+ );
89
+ const signDoc = makeSignDoc(
90
+ txBodyBytes,
91
+ authInfoBytes,
92
+ transaction.chainId,
93
+ transaction.signerData.accountNumber
94
+ );
95
+
96
+ const offlineSigner = new CosmjsOfflineSigner(this.chainId);
97
+ const { signature, signed } = await offlineSigner.signDirect(transaction.signerAddress, signDoc);
98
+
99
+ return TxRaw.fromPartial({
100
+ bodyBytes: signed.bodyBytes,
101
+ authInfoBytes: signed.authInfoBytes,
102
+ signatures: [fromBase64(signature.signature)],
103
+ });
104
+ }
105
+ }