@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,97 @@
1
+ <script lang="ts" setup>
2
+ import { PropType, computed, onMounted, ref } from 'vue';
3
+ import { Coin, CoinMetadata } from '../../../utils/type';
4
+ import { getStakingParam } from '../../../utils/http';
5
+ import { TokenUnitConverter } from '../../../utils/TokenUnitConverter';
6
+
7
+ const props = defineProps({
8
+ endpoint: {type: String, required: true },
9
+ sender: {type: String, required: true},
10
+ balances: Object as PropType<Coin[]>,
11
+ metadata: Object as PropType<Record<string, CoinMetadata>>,
12
+ params: String,
13
+ });
14
+
15
+ const params = computed(() => JSON.parse(props.params || "{}"))
16
+ const denom = ref("")
17
+ const amount = ref("")
18
+ const amountDenom = ref("")
19
+
20
+ const available = computed(() => {
21
+ const convert = new TokenUnitConverter(props.metadata)
22
+ const base = props.balances?.find(x => x.denom === denom.value) || { amount: "0", denom: denom.value }
23
+ return {
24
+ base,
25
+ display: convert.baseToUnit(base, amountDenom.value)
26
+ }
27
+ })
28
+
29
+ const msgs = computed(() => {
30
+ const convert = new TokenUnitConverter(props.metadata)
31
+ return [{
32
+ typeUrl: '/cosmos.gov.v1beta1.MsgDeposit',
33
+ value: {
34
+ depositor: props.sender,
35
+ proposalId: params.value.proposal_id,
36
+ amount: [convert.displayToBase(denom.value, {
37
+ amount: String(amount.value),
38
+ denom: amountDenom.value
39
+ })],
40
+ },
41
+ }]
42
+ })
43
+
44
+ const units = computed(() => {
45
+ if(!props.metadata || !props.metadata[denom.value]) {
46
+ amountDenom.value = denom.value
47
+ return [{denom: denom.value, exponent: 0, aliases: []}]
48
+ }
49
+ const list = props.metadata[denom.value].denom_units.sort((a, b) => b.exponent - a.exponent)
50
+ if(list.length > 0) amountDenom.value = list[0].denom
51
+ return list
52
+ })
53
+
54
+ const isValid = computed(() => {
55
+ let ok = true
56
+ let error = ""
57
+ if(!params.value.proposal_id) {
58
+ ok = false
59
+ error = "Proposal id is empty"
60
+ }
61
+ if(!(Number(amount.value) > 0)) {
62
+ ok = false
63
+ error = "Amount should be great than 0"
64
+ }
65
+ return { ok, error }
66
+ })
67
+
68
+ function initial() {
69
+ getStakingParam(props.endpoint).then(x => {
70
+ denom.value = x.params.bond_denom
71
+ })
72
+ }
73
+
74
+ defineExpose({msgs, isValid, initial})
75
+ </script>
76
+ <template>
77
+ <div>
78
+ <div class="form-control">
79
+ <label class="label">
80
+ <span class="label-text">Sender</span>
81
+ </label>
82
+ <input :value="sender" type="text" class="text-gray-600 dark:text-white input border !border-gray-300 dark:!border-gray-600" />
83
+ </div>
84
+ <div class="form-control">
85
+ <label class="label">
86
+ <span class="label-text">Amount</span>
87
+ <span>{{ available?.display.amount }}{{ available?.display.denom }}</span>
88
+ </label>
89
+ <label class="input-group">
90
+ <input v-model="amount" type="number" :placeholder="`Available: ${available?.display.amount}`" class="input border border-gray-300 dark:border-gray-600 w-full dark:text-white" />
91
+ <select v-model="amountDenom" class="select select-bordered dark:text-white">
92
+ <option v-for="u in units">{{ u.denom }}</option>
93
+ </select>
94
+ </label>
95
+ </div>
96
+ </div>
97
+ </template>
@@ -0,0 +1,189 @@
1
+ <script lang="ts" setup>
2
+ import { ComputedRef, PropType, computed, onMounted, ref } from 'vue';
3
+ import { getActiveValidators, getDelegations, getInactiveValidators, getStakingParam } from '../../../utils/http'
4
+ import { decimal2percent } from '../../../utils/format'
5
+ import { Coin, CoinMetadata } from '../../../utils/type';
6
+ import { TokenUnitConverter } from '../../../utils/TokenUnitConverter';
7
+ import { MsgBeginRedelegate } from "@initia/initia.proto/initia/mstaking/v1/tx"
8
+ const props = defineProps({
9
+ endpoint: {type: String, required: true },
10
+ sender: {type: String, required: true},
11
+ balances: Object as PropType<Coin[]>,
12
+ metadata: Object as PropType<Record<string, CoinMetadata>>,
13
+ params: String,
14
+ });
15
+ const params = computed(() => JSON.parse(props.params || "{}"))
16
+
17
+ const validator = ref('')
18
+
19
+ const activeValidators = ref([])
20
+ const inactiveValidators = ref([])
21
+ const stakingDenom = ref("")
22
+ const amount = ref("")
23
+ const amountDenom = ref("")
24
+ const delegation = ref({} as Coin)
25
+ const error = ref("")
26
+
27
+ const sourceValidator = computed(() => {
28
+ // @ts-ignore
29
+ const v = activeValidators.value.find(v => v.operator_address === params.validator_address)
30
+ if(v) {
31
+ // @ts-ignore
32
+ return `${v.description.moniker} (${decimal2percent(v.commission.commission_rates.rate)}%)`
33
+ }
34
+ return params.value.validator_address
35
+ })
36
+
37
+ function isInitiaChain(endpoint: string): boolean {
38
+ return props.endpoint.indexOf("init") !== -1;
39
+ }
40
+
41
+ const msgs = computed(() => {
42
+ const convert = new TokenUnitConverter(props.metadata);
43
+ const baseAmount = convert.displayToBase(stakingDenom.value, {
44
+ amount: String(amount.value),
45
+ denom: amountDenom.value,
46
+ });
47
+
48
+ if (isInitiaChain(props.endpoint)) {
49
+ return [
50
+ {
51
+ typeUrl: '/initia.mstaking.v1.MsgBeginRedelegate',
52
+ value: MsgBeginRedelegate.fromPartial({
53
+ delegatorAddress: props.sender,
54
+ validatorSrcAddress: params.value.validator_address,
55
+ validatorDstAddress: validator.value,
56
+ amount: [baseAmount],
57
+ }),
58
+ },
59
+ ];
60
+ } else {
61
+ return [
62
+ {
63
+ typeUrl: '/cosmos.staking.v1beta1.MsgBeginRedelegate',
64
+ value: {
65
+ delegatorAddress: props.sender,
66
+ validatorSrcAddress: params.value.validator_address,
67
+ validatorDstAddress: validator.value,
68
+ amount: baseAmount,
69
+ },
70
+ },
71
+ ];
72
+ }
73
+ });
74
+
75
+ const list: ComputedRef<{
76
+ operator_address: string,
77
+ description: {moniker: string}
78
+ commission: { commission_rates: {rate: string}}
79
+ status: string
80
+ }[]> = computed(() => {
81
+ return [...activeValidators.value, ...inactiveValidators.value]
82
+ })
83
+
84
+ const available = computed(() => {
85
+ const convert = new TokenUnitConverter(props.metadata)
86
+ const base = delegation.value || { amount: "0", denom: stakingDenom.value }
87
+ return {
88
+ base,
89
+ display: convert.baseToUnit(base, amountDenom.value)
90
+ }
91
+ })
92
+
93
+ const units = computed(() => {
94
+ if(!props.metadata || !props.metadata[stakingDenom.value]) {
95
+ amountDenom.value = stakingDenom.value
96
+ return [{denom: stakingDenom.value, exponent: 0, aliases: []}]
97
+ }
98
+ const list = props.metadata[stakingDenom.value].denom_units.sort((a, b) => b.exponent - a.exponent)
99
+ if(list.length > 0) amountDenom.value = list[0].denom
100
+ return list
101
+ })
102
+
103
+ const isValid = computed(() => {
104
+ let ok = true
105
+ let error = ""
106
+ if(!validator.value) {
107
+ ok = false
108
+ error = "Validator is empty"
109
+ }
110
+ if(!validator.value) {
111
+ ok = false
112
+ error = "Validator is empty"
113
+ }
114
+ if(!(Number(amount.value) > 0)) {
115
+ ok = false
116
+ error = "Amount should be great than 0"
117
+ }
118
+ return { ok, error }
119
+ })
120
+
121
+
122
+ function initial() {
123
+ getDelegations(props.endpoint, params.value.validator_address, props.sender).then(x => {
124
+ const balance = x.delegation_response.balance;
125
+ if (isInitiaChain(props.endpoint)) {
126
+ delegation.value = Array.isArray(balance) ? balance.find(b => b.denom === 'uinit') || { amount: "0", denom: "uinit" } : balance;
127
+ } else {
128
+ delegation.value = Array.isArray(balance) ? balance[0] || { amount: "0", denom: stakingDenom.value } : balance;
129
+ }
130
+ }).catch(err => {
131
+ error.value = err
132
+ })
133
+
134
+ getStakingParam(props.endpoint).then((x) => {
135
+ stakingDenom.value = x.params.bond_denom || "";
136
+ // unbondingTime.value = x.params.unbonding_time;
137
+ });
138
+
139
+ getActiveValidators(props.endpoint).then(x => {
140
+ activeValidators.value = x.validators
141
+ validator.value = x.validators.find(v => v.description.identity === '6783E9F948541962')?.operator_address
142
+ })
143
+ }
144
+
145
+ defineExpose({msgs, isValid, initial})
146
+ </script>
147
+ <template>
148
+ <div>
149
+ <div class="form-control">
150
+ <label class="label">
151
+ <span class="label-text">Sender</span>
152
+ </label>
153
+ <input :value="sender" type="text" class="text-gray-600 dark:text-white input border !border-gray-300 dark:!border-gray-600" />
154
+ </div>
155
+ <div class="form-control">
156
+ <label class="label">
157
+ <span class="label-text">Source Validator</span>
158
+ </label>
159
+ <input :value="sourceValidator" type="text" class="input border border-gray-300 dark:border-gray-600 dark:text-white" readonly/>
160
+ </div>
161
+ <div class="form-control">
162
+ <label class="label">
163
+ <span class="label-text">Destination Validator</span>
164
+ </label>
165
+ <select v-model="validator" class="select select-bordered dark:text-white">
166
+ <option value="">Select a validator</option>
167
+ <option v-for="v in list" :value="v.operator_address">
168
+ {{ v.description.moniker }} ({{ decimal2percent(v.commission.commission_rates.rate) }}%)
169
+ <span v-if="v.status !== 'BOND_STATUS_BONDED'">x</span>
170
+ </option>
171
+ </select>
172
+ </div>
173
+ <div class="form-control">
174
+ <label class="label">
175
+ <span class="label-text">Amount</span>
176
+ <span>{{ available?.display.amount }}{{ available?.display.denom }}</span>
177
+ </label>
178
+ <label class="input-group">
179
+ <input v-model="amount" type="number" :placeholder="`Available: ${available?.display.amount}${available?.display.denom}`" class="input border border-gray-300 dark:border-gray-600 w-full dark:text-white" />
180
+ <select v-model="amountDenom" class="select select-bordered dark:text-white">
181
+ <option v-for="u in units">{{ u.denom }}</option>
182
+ </select>
183
+ </label>
184
+ </div>
185
+ <div class="text-error">
186
+ {{ error }}
187
+ </div>
188
+ </div>
189
+ </template>
@@ -0,0 +1,142 @@
1
+ <script lang="ts" setup>
2
+ import { PropType, computed, onMounted, ref } from 'vue';
3
+ import {
4
+ getBalance,
5
+ } from '../../../utils/http';
6
+ import { Coin, CoinMetadata } from '../../../utils/type';
7
+ import { TokenUnitConverter } from '../../../utils/TokenUnitConverter';
8
+ const props = defineProps({
9
+ endpoint: { type: String, required: true },
10
+ sender: { type: String, required: true },
11
+ balances: Object as PropType<Coin[]>,
12
+ metadata: Object as PropType<Record<string, CoinMetadata>>,
13
+ params: String,
14
+ });
15
+
16
+ const amount = ref('');
17
+ const recipient = ref('');
18
+ const denom = ref('');
19
+ const amountDenom = ref('')
20
+
21
+ const msgs = computed(() => {
22
+ const convert = new TokenUnitConverter(props.metadata)
23
+ return [
24
+ {
25
+ typeUrl: '/cosmos.bank.v1beta1.MsgSend',
26
+ value: {
27
+ fromAddress: props.sender,
28
+ toAddress: recipient.value,
29
+ amount: [
30
+ convert.displayToBase(denom.value, {
31
+ amount: String(amount.value),
32
+ denom: amountDenom.value
33
+ })
34
+ ],
35
+ },
36
+ },
37
+ ];
38
+ });
39
+
40
+ const available = computed(() => {
41
+ const base = (
42
+ props.balances?.find((x) => x.denom === denom.value) || {
43
+ amount: '0',
44
+ denom: '-',
45
+ }
46
+ )
47
+ const convert = new TokenUnitConverter(props.metadata)
48
+ return {
49
+ base,
50
+ display: convert.baseToUnit(base, amountDenom.value)
51
+ };
52
+ });
53
+
54
+ const showBalances = computed(() => {
55
+ const convert = new TokenUnitConverter(props.metadata)
56
+ return props.balances?.map(b => ({
57
+ base: b,
58
+ display: convert.baseToDisplay(b)
59
+ })) || []
60
+ })
61
+
62
+ const units = computed(() => {
63
+ if(!props.metadata || !props.metadata[denom.value]) {
64
+ amountDenom.value = denom.value
65
+ return [{denom: denom.value, exponent: 0, aliases: []}]
66
+ }
67
+ const list = props.metadata[denom.value].denom_units.sort((a, b) => b.exponent - a.exponent)
68
+ if(list.length > 0) amountDenom.value = list[0].denom
69
+ return list
70
+ })
71
+
72
+ const isValid = computed(() => {
73
+ let ok = true
74
+ let error = ""
75
+ if(!recipient.value) {
76
+ ok = false
77
+ error = "Recipient is empty"
78
+ }
79
+ if(!(Number(amount.value) > 0)) {
80
+ ok = false
81
+ error = "Amount should be great than 0"
82
+ }
83
+ return { ok, error }
84
+ })
85
+
86
+
87
+ function initial() {
88
+ denom.value = props.params?.fees?.denom || '';
89
+ // getStakingParam(props.endpoint).then((x) => {
90
+ // denom.value = x.params?.bond_denom;
91
+ // });
92
+ }
93
+
94
+ function formatDenom(v: any) {
95
+ return String(v).substring(0, 10)
96
+ }
97
+
98
+ defineExpose({msgs, isValid, initial})
99
+ </script>
100
+ <template>
101
+ <div class="dark:text-gray-400">
102
+ <div class="form-control">
103
+ <label class="label">
104
+ <span class="label-text">Sender</span>
105
+ </label>
106
+ <input :value="sender" type="text" class="text-gray-600 dark:text-white input border !border-gray-300 dark:!border-gray-600" />
107
+ </div>
108
+ <div class="form-control">
109
+ <label class="label">
110
+ <span class="label-text">Balances</span>
111
+ </label>
112
+ <select v-model="denom" class="select select-bordered dark:text-white">
113
+ <option value="">Select a token</option>
114
+ <option v-for="{base, display} in showBalances" :value="base.denom">
115
+ {{ display.amount }} {{ display.denom }}
116
+ </option>
117
+ </select>
118
+ </div>
119
+ <div class="form-control">
120
+ <label class="label">
121
+ <span class="label-text">Recipient</span>
122
+ </label>
123
+ <input
124
+ v-model="recipient"
125
+ type="text"
126
+ class="input border border-gray-300 dark:border-gray-600 dark:text-white"
127
+ />
128
+ </div>
129
+ <div class="form-control">
130
+ <label class="label">
131
+ <span class="label-text">Amount</span>
132
+ <span>{{ available.display.amount }} {{ formatDenom(available.display.denom) }}</span>
133
+ </label>
134
+ <label class="input-group">
135
+ <input v-model="amount" type="number" :placeholder="`Available: ${available?.display.amount}`" class="input border border-gray-300 dark:border-gray-600 w-full dark:text-white" />
136
+ <select v-model="amountDenom" class="select select-bordered dark:text-white">
137
+ <option v-for="u in units" :value="u.denom">{{ formatDenom(u.denom) }}</option>
138
+ </select>
139
+ </label>
140
+ </div>
141
+ </div>
142
+ </template>
@@ -0,0 +1,248 @@
1
+ <script lang="ts" setup>
2
+ import { ComputedRef, PropType, computed, onMounted, ref } from 'vue';
3
+ import { getBalance, getDenomTraces } from '../../../utils/http';
4
+ import { Coin, CoinMetadata } from '../../../utils/type';
5
+ import ChainRegistryClient from '@ping-pub/chain-registry-client';
6
+ import { IBCPath } from '@ping-pub/chain-registry-client/dist/types';
7
+ import dayjs from 'dayjs';
8
+ import utc from 'dayjs/plugin/utc';
9
+ import { TokenUnitConverter } from '../../../utils/TokenUnitConverter';
10
+ dayjs.extend(utc);
11
+
12
+ const props = defineProps({
13
+ endpoint: { type: String, required: true },
14
+ sender: { type: String, required: true },
15
+ balances: Object as PropType<Coin[]>,
16
+ metadata: Object as PropType<Record<string, CoinMetadata>>,
17
+ params: String,
18
+ });
19
+ const params = computed(() => JSON.parse(props.params || "{}"))
20
+ const chainName = params.value.chain_name;
21
+
22
+ const amount = ref('');
23
+ const amountDenom = ref('');
24
+ const recipient = ref('');
25
+ const denom = ref('');
26
+ const dest = ref('');
27
+ const chains = ref([] as IBCPath[]);
28
+ const sourceChain = ref(
29
+ {} as { channel_id: string; port_id: string } | undefined
30
+ );
31
+ const ibcDenomTraces = ref(
32
+ {} as Record<string, { path: string; base_denom: string }>
33
+ );
34
+
35
+ const client = new ChainRegistryClient();
36
+
37
+ const msgs = computed(() => {
38
+ const timeout = dayjs().add(1, 'hour');
39
+ const convert = new TokenUnitConverter(props.metadata);
40
+ return [
41
+ {
42
+ typeUrl: '/ibc.applications.transfer.v1.MsgTransfer',
43
+ value: {
44
+ sourcePort: sourceChain.value?.port_id || '',
45
+ sourceChannel: sourceChain.value?.channel_id || '',
46
+ token: convert.displayToBase(denom.value, {
47
+ amount: String(amount.value),
48
+ denom: amountDenom.value,
49
+ }),
50
+ sender: props.sender,
51
+ receiver: recipient.value,
52
+ timeoutTimestamp: String(timeout.utc().valueOf() * 1000000),
53
+ },
54
+ },
55
+ ];
56
+ });
57
+ const destDisabled = computed(() => {
58
+ const disable = denom.value.startsWith('ibc/');
59
+ if (disable) dest.value = '';
60
+ return disable;
61
+ });
62
+
63
+ function selectDest() {
64
+ client.fetchIBCPathInfo(dest.value).then((info) => {
65
+ if (info.chain_1.chain_name === chainName) {
66
+ sourceChain.value = info.channels.find(
67
+ (x) => x.chain_1.port_id === 'transfer'
68
+ )?.chain_1;
69
+ } else {
70
+ sourceChain.value = info.channels.find(
71
+ (x) => x.chain_2.port_id === 'transfer'
72
+ )?.chain_2;
73
+ }
74
+ });
75
+ }
76
+
77
+ function updateIBCToken() {
78
+ const hash = String(denom.value).replace('ibc/', '');
79
+ if (!denom.value.startsWith('ibc/')) return;
80
+ if (ibcDenomTraces.value[denom.value]) {
81
+ const trace = ibcDenomTraces.value[denom.value];
82
+ const split = trace.path.split('/');
83
+ sourceChain.value = {
84
+ channel_id: split[1],
85
+ port_id: split[0],
86
+ };
87
+ } else {
88
+ getDenomTraces(props.endpoint, hash).then((trace) => {
89
+ ibcDenomTraces.value[denom.value] = trace.denom_trace;
90
+ const split = trace.denom_trace.path.split('/');
91
+ sourceChain.value = {
92
+ channel_id: split[1],
93
+ port_id: split[0],
94
+ };
95
+ });
96
+ }
97
+ }
98
+
99
+ const available = computed(() => {
100
+ const base = props.balances?.find((x) => x.denom === denom.value) || {
101
+ amount: '0',
102
+ denom: '-',
103
+ };
104
+ const convert = new TokenUnitConverter(props.metadata);
105
+ return {
106
+ base,
107
+ display: convert.baseToUnit(base, amountDenom.value),
108
+ };
109
+ });
110
+
111
+ const showBalances = computed(() => {
112
+ const convert = new TokenUnitConverter(props.metadata);
113
+ return (
114
+ props.balances?.map((b) => ({
115
+ base: b,
116
+ display: convert.baseToDisplay(b),
117
+ })) || []
118
+ );
119
+ });
120
+
121
+ const units = computed(() => {
122
+ if (!props.metadata || !props.metadata[denom.value]) {
123
+ amountDenom.value = denom.value;
124
+ return [{ denom: denom.value, exponent: 0, aliases: [] }];
125
+ }
126
+ const list = props.metadata[denom.value].denom_units.sort(
127
+ (a, b) => b.exponent - a.exponent
128
+ );
129
+ if (list.length > 0) amountDenom.value = list[0].denom;
130
+ return list;
131
+ });
132
+
133
+ const isValid = computed(() => {
134
+ let ok = true;
135
+ let error = '';
136
+ if (!sourceChain.value?.channel_id || !sourceChain.value.port_id) {
137
+ ok = false;
138
+ error = 'Destination chain is empty';
139
+ }
140
+ if (!recipient.value) {
141
+ ok = false;
142
+ error = 'Recipient is empty';
143
+ }
144
+ if (!(Number(amount.value) > 0)) {
145
+ ok = false;
146
+ error = 'Amount should be great than 0';
147
+ }
148
+ return { ok, error };
149
+ });
150
+
151
+ function initial() {
152
+ client.fetchIBCPaths().then((paths) => {
153
+ chains.value = paths.filter((x) => x.path.indexOf(chainName) > -1);
154
+ });
155
+
156
+ getStakingParam(props.endpoint).then((x) => {
157
+ denom.value = x.params.bond_denom;
158
+ });
159
+ }
160
+
161
+ function formatDenom(v: any) {
162
+ return String(v).substring(0, 10)
163
+ }
164
+
165
+ defineExpose({ msgs, isValid, initial });
166
+ </script>
167
+ <template>
168
+ <div>
169
+ <div class="form-control">
170
+ <label class="label">
171
+ <span class="label-text">Sender</span>
172
+ </label>
173
+ <input
174
+ :value="sender"
175
+ type="text"
176
+ class="text-gray-600 dark:text-white input border !border-gray-300 dark:!border-gray-600"
177
+ />
178
+ </div>
179
+ <div class="form-control">
180
+ <label class="label">
181
+ <span class="label-text">Balances</span>
182
+ </label>
183
+ <select
184
+ v-model="denom"
185
+ class="select select-bordered dark:text-white"
186
+ @change="updateIBCToken"
187
+ >
188
+ <option value="">Select a token</option>
189
+ <option
190
+ v-for="{ base, display } in showBalances"
191
+ :value="base.denom"
192
+ >
193
+ {{ display.amount }} {{ formatDenom(display.denom) }}
194
+ </option>
195
+ </select>
196
+ </div>
197
+ <div class="form-control">
198
+ <label class="label">
199
+ <span class="label-text">Destination</span>
200
+ <span v-if="sourceChain" class="text-xs"
201
+ >{{ sourceChain.channel_id }}/{{
202
+ sourceChain.port_id
203
+ }}</span
204
+ >
205
+ </label>
206
+ <select
207
+ v-model="dest"
208
+ class="select select-bordered capitalize dark:text-white"
209
+ @change="selectDest"
210
+ :disabled="destDisabled"
211
+ >
212
+ <option value="">Select Destination</option>
213
+ <option v-for="v in chains" :value="v.path">
214
+ {{ v.from === params.chain_name ? v.to : v.from }}
215
+ </option>
216
+ </select>
217
+ </div>
218
+ <div class="form-control">
219
+ <label class="label">
220
+ <span class="label-text">Recipient</span>
221
+ </label>
222
+ <input
223
+ v-model="recipient"
224
+ type="text"
225
+ class="input border border-gray-300 dark:border-gray-600 dark:text-white"
226
+ />
227
+ </div>
228
+ <div class="form-control">
229
+ <label class="label">
230
+ <span class="label-text">Amount</span>
231
+ <span>
232
+ {{ available?.display.amount}} {{ formatDenom(available?.display.denom) }}
233
+ </span>
234
+ </label>
235
+ <label class="input-group">
236
+ <input
237
+ v-model="amount"
238
+ type="number"
239
+ :placeholder="`Available: ${available?.display.amount}`"
240
+ class="input border border-gray-300 dark:border-gray-600 w-full dark:text-white"
241
+ />
242
+ <select v-model="amountDenom" class="select select-bordered dark:text-white">
243
+ <option v-for="u in units" :value="u.denom">{{ formatDenom(u.denom) }}</option>
244
+ </select>
245
+ </label>
246
+ </div>
247
+ </div>
248
+ </template>