diff --git a/components/overlays/ChooseWalletOverlay.vue b/components/overlays/ChooseWalletOverlay.vue index 1a9ac0c..bf2b322 100644 --- a/components/overlays/ChooseWalletOverlay.vue +++ b/components/overlays/ChooseWalletOverlay.vue @@ -76,15 +76,37 @@ +
+

+ your currently selected account is {{ accountStore.getAddress }} +

+
+ +
+
-

+

please allow this app to read your balance by signing the upcoming request in your extension

-

this window will close once a balance could be fetched

+

+ this window will close once a balance could be fetched +

@@ -94,15 +116,35 @@ import { connectExtension, extensionAccounts, - injectorForAddress, } from "~/lib/signerExtensionUtils"; import OverlayDialog from "~/components/overlays/OverlayDialog.vue"; -import { defineProps, computed, ref, watch } from "vue"; +import { computed, defineProps, ref, watch } from "vue"; import { useAccount } from "~/store/account.ts"; +import { encodeAddress } from "@polkadot/util-crypto"; +import { SessionProxyRole } from "~/lib/sessionProxyStorage"; const accountStore = useAccount(); +const currentExtensionAccount = ref(""); const selectedExtensionAccount = ref(""); +const selectedExtensionAccountIsNew = computed(() => { + try { + const selectedAddressEncoded = encodeAddress( + selectedExtensionAccount.value, + accountStore.getSs58Format, + ); + console.log( + "comparing", + currentExtensionAccount.value, + " to ", + selectedAddressEncoded, + ); + return selectedAddressEncoded !== currentExtensionAccount.value; + } catch (e) { + return false; + } +}); + const props = defineProps({ createTestingAccount: { type: Function, @@ -124,7 +166,23 @@ const props = defineProps({ type: Boolean, required: false, }, + changeSessionAuthorization: { + type: Function, + required: false, + }, }); + +watch( + () => props.show, + (show) => { + if (show) { + console.log("current extension account: ", accountStore.getAddress); + currentExtensionAccount.value = accountStore.getAddress; + //selectedExtensionAccount.value = ""; + } + }, +); + const hasCreateTestingAccountFn = computed( () => typeof props.createTestingAccount === "function", ); @@ -139,10 +197,15 @@ const closeProxy = () => { }; watch(selectedExtensionAccount, async (selectedAddress) => { - if (selectedAddress) { + if (selectedAddress && selectedExtensionAccountIsNew.value) { props.onExtensionAccountChange(selectedAddress); } }); - + diff --git a/components/overlays/SessionProxiesOverlay.vue b/components/overlays/SessionProxiesOverlay.vue new file mode 100644 index 0000000..2851369 --- /dev/null +++ b/components/overlays/SessionProxiesOverlay.vue @@ -0,0 +1,384 @@ + + + + diff --git a/components/tabs/MessagingTab.vue b/components/tabs/MessagingTab.vue index 899144e..b125602 100644 --- a/components/tabs/MessagingTab.vue +++ b/components/tabs/MessagingTab.vue @@ -402,6 +402,7 @@ import { useNotes } from "@/store/notes.ts"; import { Note, NoteDirection } from "@/lib/notes"; import { divideBigIntToFloat } from "@/helpers/numbers"; import NoteDetailsOverlay from "~/components/overlays/NoteDetailsOverlay.vue"; +import { SessionProxyRole } from "~/lib/sessionProxyStorage"; const identityLut = [...polkadotPeopleIdentities, ...wellKnownIdentities]; @@ -580,7 +581,6 @@ const submitSendForm = () => { const sendPrivately = async () => { console.log("sending message on incognitee"); txStatus.value = "⌛ sending message privately on incognitee"; - const amount = BigInt(0); const account = accountStore.account; if ( accountStore.getDecimalBalanceTransferable(incogniteeSidechain.value) < @@ -608,16 +608,18 @@ const sendPrivately = async () => { ); await incogniteeStore.api - .trustedBalanceTransfer( + .trustedSendNote( account, incogniteeStore.shard, incogniteeStore.fingerprint, accountStore.getAddress, conversationAddress.value, - amount, note, { signer: accountStore.injector?.signer, + delegate: accountStore.sessionProxyForRole( + SessionProxyRole.NonTransfer, + ), nonce: nonce, }, ) @@ -636,7 +638,7 @@ const handleTopResult = (result, successMsg?) => { txStatus.value = "😀 included in sidechain block: " + result.status.asInSidechainBlock; } - //update history to see successfuly action immediately + //update history to see successful action immediately props.updateNotes(); return; } diff --git a/components/tabs/VouchersTab.vue b/components/tabs/VouchersTab.vue index 99241ec..bbafb42 100644 --- a/components/tabs/VouchersTab.vue +++ b/components/tabs/VouchersTab.vue @@ -378,6 +378,7 @@ import { forgetAllVouchersForShard, forgetVoucherForShard, } from "~/lib/voucherStorage"; +import { SessionProxyRole } from "~/lib/sessionProxyStorage"; const accountStore = useAccount(); const incogniteeStore = useIncognitee(); @@ -488,6 +489,7 @@ const fundNewVoucher = async () => { note, { signer: accountStore.injector?.signer, + delegate: accountStore.sessionProxyForRole(SessionProxyRole.Any), nonce: nonce, }, ) diff --git a/components/tabs/WalletTab.vue b/components/tabs/WalletTab.vue index b16a6ed..08a85af 100644 --- a/components/tabs/WalletTab.vue +++ b/components/tabs/WalletTab.vue @@ -2,7 +2,7 @@
- -
{ txStatus.value = "😀 included in sidechain block: " + result.status.asInSidechainBlock; } - //update history to see successfuly action immediately + //update history to see successful action immediately props.updateNotes(); return; } @@ -1284,6 +1279,7 @@ const unshield = async () => { amount, { signer: accountStore.injector?.signer, + delegate: accountStore.sessionProxyForRole(SessionProxyRole.Any), nonce: nonce, }, ) @@ -1332,6 +1328,7 @@ const sendPrivately = async () => { note, { signer: accountStore.injector?.signer, + delegate: accountStore.sessionProxyForRole(SessionProxyRole.Any), nonce: nonce, }, ) @@ -1359,6 +1356,9 @@ const submitGuess = async () => { guess.value, { signer: accountStore.injector?.signer, + delegate: accountStore.sessionProxyForRole( + SessionProxyRole.NonTransfer, + ), nonce: nonce, }, ) @@ -1431,7 +1431,7 @@ const closePrivacyInfo = () => { const showObtainTokenOverlay = ref(false); const openObtainTokenOverlay = () => { - if (!enableActions.value) { + if (!props?.enableActions) { console.error("network not live"); return; } @@ -1443,7 +1443,7 @@ const closeObtainTokenOverlay = () => { const showShieldOverlay = ref(false); const openShieldOverlay = () => { - if (!enableActions.value) { + if (!props?.enableActions) { console.error("network not live"); return; } @@ -1458,7 +1458,7 @@ const closeShieldOverlay = () => { const showFaucetOverlay = ref(false); const openFaucetOverlay = () => { - if (!enableActions.value) { + if (!props?.enableActions) { console.error("network not live"); return; } @@ -1470,7 +1470,7 @@ const closeFaucetOverlay = () => { const showUnshieldOverlay = ref(false); const openUnshieldOverlay = () => { - if (!enableActions.value) { + if (!props?.enableActions) { console.error("network not live"); return; } @@ -1484,7 +1484,7 @@ const closeUnshieldOverlay = () => { }; const showReceiveOverlay = ref(false); const openReceiveOverlay = () => { - if (!enableActions.value) { + if (!props?.enableActions) { console.error("network not live"); return; } @@ -1495,7 +1495,7 @@ const closeReceiveOverlay = () => { }; const showPrivateSendOverlay = ref(false); const openPrivateSendOverlay = () => { - if (!enableActions.value) { + if (!props?.enableActions) { console.error("network not live"); return; } @@ -1517,7 +1517,7 @@ const closePrivateSendOverlay = () => { const showGuessTheNumberOverlay = ref(false); const openGuessTheNumberOverlay = () => { - if (!enableActions.value) { + if (!props?.enableActions) { console.error("network not live"); return; } @@ -1599,10 +1599,10 @@ const props = defineProps({ type: Function, required: true, }, -}); - -const enableActions = computed(() => { - return isLive.value || forceLive.value; + enableActions: { + type: Boolean, + required: true, + }, }); diff --git a/configs/incognitee.ts b/configs/incognitee.ts index e96cf10..9d8ed98 100644 --- a/configs/incognitee.ts +++ b/configs/incognitee.ts @@ -5,3 +5,5 @@ export const INCOGNITEE_GTN_GUESS_FEE = 0.1; // TEER or PAS, decimals are respec export const INCOGNITEE_UNSHIELDING_FEE = 3 * INCOGNITEE_TX_FEE; // TEER or PAS, decimals are respected export const INCOGNITEE_SHIELDING_FEE_FRACTION = 0.00175; // 0.175% of the shielding amount + +export const INCOGNITEE_SESSION_PROXY_DEPOSIT = 0.5; // TEER or PAS, decimals are respected diff --git a/lib/sessionProxyStorage.ts b/lib/sessionProxyStorage.ts new file mode 100644 index 0000000..9729649 --- /dev/null +++ b/lib/sessionProxyStorage.ts @@ -0,0 +1,34 @@ +export enum SessionProxyRole { + ReadBalance = "readBalance", + ReadAny = "readAny", + NonTransfer = "nonTransfer", + Any = "any", + TransferAllowance = "transferAllowance", +} + +export const sessionProxyRoleOrder = [ + SessionProxyRole.ReadBalance, + SessionProxyRole.ReadAny, + SessionProxyRole.NonTransfer, + SessionProxyRole.TransferAllowance, + SessionProxyRole.Any, +]; + +export function isRoleAtLeast( + role1: SessionProxyRole, + role2: SessionProxyRole, +): boolean { + return roleOrder.indexOf(role1) >= roleOrder.indexOf(role2); +} + +export class SessionProxyCredentials { + role: SessionProxyRole; + expiry: Date; + seed: Uint8Array; + + constructor(role: SessionProxyRole, expiry: Date, seed: Uint8Array) { + this.role = role; + this.expiry = expiry; + this.seed = seed; + } +} diff --git a/package.json b/package.json index fcc34cd..986b5b3 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,8 @@ "vue-router": "^4.3.2" }, "dependencies": { - "@encointer/util": "^0.18.0-alpha.2", - "@encointer/worker-api": "^0.18.0-alpha.2", + "@encointer/util": "^0.18.0", + "@encointer/worker-api": "^0.18.0", "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@headlessui/vue": "^1.7.22", "@heroicons/vue": "^2.1.3", diff --git a/pages/index.vue b/pages/index.vue index 51448a8..007c60a 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -12,6 +12,7 @@ ref="walletTabRef" :updateNotes="updateNotes" :fetchOlderBucket="fetchOlderBucket" + :enableActions="enableActions" />
@@ -97,6 +98,14 @@ + + + @@ -111,7 +121,8 @@ import WalletTab from "~/components/tabs/WalletTab.vue"; import VouchersTab from "~/components/tabs/VouchersTab.vue"; import ChooseWalletOverlay from "~/components/overlays/ChooseWalletOverlay.vue"; -import { computed } from "vue"; +import SessionProxiesOverlay from "~/components/overlays/SessionProxiesOverlay.vue"; +import { computed, onMounted, onUnmounted, ref, watch } from "vue"; import { chainConfigs } from "@/configs/chains.ts"; import { useAccount } from "@/store/account.ts"; import { useIncognitee } from "@/store/incognitee.ts"; @@ -126,7 +137,6 @@ import { mnemonicToMiniSecret, } from "@polkadot/util-crypto"; import { useInterval } from "@vueuse/core"; -import { onUnmounted, onMounted, ref, watch } from "vue"; import { useRouter } from "vue-router"; import { eventBus } from "@/helpers/eventBus"; import { @@ -134,16 +144,17 @@ import { injectorForAddress, } from "@/lib/signerExtensionUtils"; import { - loadEnv, - shieldingTarget, - incogniteeSidechain, incogniteeShard, + incogniteeSidechain, isLive, + loadEnv, + shieldingTarget, } from "@/lib/environmentConfig"; import { useSystemHealth } from "@/store/systemHealth"; import { useNotes } from "~/store/notes"; import { formatMoment } from "~/helpers/date"; import { Note, NoteDirection } from "~/lib/notes"; +import { SessionProxyRole } from "@/lib/sessionProxyStorage.ts"; import MessagingTab from "~/components/tabs/MessagingTab.vue"; import SwapTab from "~/components/tabs/SwapTab.vue"; import GovTab from "~/components/tabs/GovTab.vue"; @@ -168,9 +179,11 @@ const shieldingTargetApi = ref(null); const isProd = computed( () => chainConfigs[shieldingTarget.value].faucetUrl === undefined, ); + const onExtensionAccountChange = async (selectedAddress) => { dropSubscriptions(); console.log("user selected extension account:", selectedAddress); + accountStore.resetState(); accountStore.setAccount(selectedAddress.toString()); accountStore.setInjector(await injectorForAddress(accountStore.getAddress)); isUpdatingIncogniteeBalance.value = false; @@ -205,7 +218,7 @@ const fetchIncogniteeBalance = async () => { ); } getterMap[accountStore.account] = - await incogniteeStore.api.accountInfoGetter( + await incogniteeStore.api.accountInfoAndSessionProxiesGetter( accountStore.account, incogniteeStore.shard, { signer: injector?.signer }, @@ -226,10 +239,14 @@ const fetchIncogniteeBalance = async () => { await getterMap[accountStore.account] .send() - .then((accountInfo) => { + .then((accountInfoAndSessionProxies) => { + const accountInfo = accountInfoAndSessionProxies.account_info; + const proxies = accountInfoAndSessionProxies.session_proxies; console.debug( `current account info L2: ${accountInfo} on shard ${incogniteeStore.shard}`, ); + console.debug(`session proxies: ${proxies}`); + storeSessionProxies(proxies); accountStore.setBalanceFree( BigInt(accountInfo.data.free), incogniteeSidechain.value, @@ -241,6 +258,15 @@ const fetchIncogniteeBalance = async () => { isFetchingIncogniteeBalance.value = false; isUpdatingIncogniteeBalance.value = false; isChoosingAccount.value = false; + if ( + proxies.length == 0 && + accountStore.hasInjector && + !accountStore.hasDeclinedSessionProxy && + accountStore.getDecimalBalanceFree(incogniteeSidechain.value) > 0 + ) { + openAuthorizeSessionOverlay(); + } + //openAuthorizeSessionOverlay(); }) .catch((err) => { console.error(`[fetchIncogniteeBalance] error ${err}`); @@ -248,6 +274,18 @@ const fetchIncogniteeBalance = async () => { }); }; +const storeSessionProxies = (proxies) => { + for (const proxy of proxies) { + const localKeyring = new Keyring({ type: "sr25519" }); + const seed = hexToU8a(proxy.seed.toString()); + const account = localKeyring.addFromSeed(seed); + accountStore.addSessionProxy( + account, + seed, + proxy.role.toString() as SessionProxyRole, + ); + } +}; const fetchNetworkStatus = async () => { const promises = []; if (shieldingTargetApi.value?.isReady) { @@ -335,10 +373,9 @@ const fetchOlderBucket = async () => { /// returns the date as moment before which all notes have been purged from sidechain state const oldestMomentInNoteBuckets = computed(() => { - console.log( - "oldest moment is " + noteBucketsInfo.value?.first.unwrap().begins_at, - ); - return noteBucketsInfo.value?.first.unwrap().begins_at?.toNumber(); + const beginsAt = noteBucketsInfo.value?.first.unwrap().begins_at; + console.log("oldest moment is " + beginsAt?.toNumber()); + return beginsAt ? beginsAt.toNumber() : NaN; }); const bucketsCount = computed(() => { @@ -352,10 +389,12 @@ const bucketsCount = computed(() => { const unfetchedBucketsCount = computed(() => { if (!noteBucketsInfo.value) return 0; - return ( - firstNoteBucketIndexFetched.value ? firstNoteBucketIndexFetched.value - - noteBucketsInfo.value.first.unwrap().index : noteBucketsInfo.value.last.unwrap().index - noteBucketsInfo.value.first.unwrap().index +1 - ); + return firstNoteBucketIndexFetched.value + ? firstNoteBucketIndexFetched.value - + noteBucketsInfo.value.first.unwrap().index + : noteBucketsInfo.value.last.unwrap().index - + noteBucketsInfo.value.first.unwrap().index + + 1; }); const fetchIncogniteeNotes = async ( @@ -372,10 +411,17 @@ const fetchIncogniteeNotes = async ( return; } const mapKey = `notesFor:${accountStore.account}:${bucketIndex}`; + const sessionProxy = accountStore.sessionProxyForRole( + SessionProxyRole.ReadAny, + ); + console.debug( + "[fetchIncogniteeNotes] sessionProxy: " + sessionProxy?.address, + ); const injector = accountStore.hasInjector ? accountStore.injector : null; + console.debug("[fetchIncogniteeNotes] injector: " + injector); try { if (!getterMap[mapKey]) { - if (injector) { + if (injector && sessionProxy == null) { if (skip_if_signer_needed) { console.log( "skipping automated fetchIncogniteeNotes because signer is needed", @@ -391,7 +437,7 @@ const fetchIncogniteeNotes = async ( accountStore.account, bucketIndex, incogniteeStore.shard, - { signer: injector?.signer }, + { delegate: sessionProxy, signer: injector?.signer }, ); } else { console.debug(`fetching incognitee notes using cached getter`); @@ -521,6 +567,43 @@ const fetchIncogniteeNotes = async ( `[${formatMoment(note.timestamp?.toNumber())}] unknown relation to transfer: ${typedCall}`, ); } + } else if (call.isSendNote) { + const typedCall = call.asSendNote; + console.debug( + `[${formatMoment(note.timestamp?.toNumber())}] send note: ${typedCall}`, + ); + const from = encodeAddress( + typedCall[0], + accountStore.getSs58Format, + ); + const to = encodeAddress(typedCall[1], accountStore.getSs58Format); + if (from === accountStore.getAddress) { + noteStore.addNote( + new Note( + "Outgoing Note", + NoteDirection.Outgoing, + to, + BigInt(0), + new Date(note.timestamp?.toNumber()), + typedCall[2].toString(), + ), + ); + } else if (to === accountStore.getAddress) { + noteStore.addNote( + new Note( + "Incoming Note", + NoteDirection.Incoming, + from, + BigInt(0), + new Date(note.timestamp?.toNumber()), + typedCall[2].toString(), + ), + ); + } else { + console.error( + `[${formatMoment(note.timestamp?.toNumber())}] unknown relation to transfer: ${typedCall}`, + ); + } } else if (call.isGuessTheNumber) { const typedCall = call.asGuessTheNumber.asGuess; console.debug( @@ -536,6 +619,25 @@ const fetchIncogniteeNotes = async ( null, ), ); + } else if (call.isAddSessionProxy) { + const typedCall = call.asAddSessionProxy; + const proxy = encodeAddress( + typedCall[1], + accountStore.getSs58Format, + ); + console.debug( + `[${formatMoment(note.timestamp?.toNumber())}] add session proxy: ${typedCall}`, + ); + noteStore.addNote( + new Note( + `Add Session Proxy (${typedCall[2].role})`, + NoteDirection.None, + proxy, + null, + new Date(note.timestamp?.toNumber()), + null, + ), + ); } else { console.error( `[${formatMoment(note.timestamp?.toNumber())}] unknown call: ${call}`, @@ -787,6 +889,12 @@ const dropSubscriptions = () => { accountStore.setInjector(null); }; +const changeSessionProxies = () => { + closeChooseWalletOverlay(); + isUpdatingIncogniteeBalance.value = false; + openAuthorizeSessionOverlay(); +}; + const createTestingAccount = async () => { await cryptoWaitReady().then(() => { dropSubscriptions(); @@ -826,6 +934,20 @@ const closeNewWalletOverlay = () => { showNewWalletOverlay.value = false; }; +const showAuthorizeSessionOverlay = ref(false); +const openAuthorizeSessionOverlay = () => { + if (!enableActions.value) { + console.error("network not live"); + return; + } + showAuthorizeSessionOverlay.value = true; +}; +const closeAuthorizeSessionOverlay = (optout: boolean) => { + if (optout) { + accountStore.declineSessionProxy(); + } + showAuthorizeSessionOverlay.value = false; +}; const showChooseWalletOverlay = ref(false); const openChooseWalletOverlay = () => { if (!enableActions.value) { diff --git a/store/account.ts b/store/account.ts index 5aebd56..575de1f 100644 --- a/store/account.ts +++ b/store/account.ts @@ -5,6 +5,10 @@ import type { InjectedExtension } from "@polkadot/extension-inject/types"; import { ChainId } from "@/configs/chains"; import { encodeAddress } from "@polkadot/util-crypto"; import { divideBigIntToFloat, formatDecimalBalance } from "@/helpers/numbers"; +import { + SessionProxyRole, + sessionProxyRoleOrder, +} from "@/lib/sessionProxyStorage.ts"; export const useAccount = defineStore("account", { state: () => ({ @@ -12,6 +16,12 @@ export const useAccount = defineStore("account", { account: null, // optional signer extension injector: null, + // optional session proxy credentials + sessionProxies: >{}, + // optional session proxy minisecrets + sessionProxySeeds: >{}, + // remember if the user has declined creating a proxy + sessionProxyDeclined: false, // free balance per chain balanceFree: >{}, // reserved balance per chain @@ -54,6 +64,53 @@ export const useAccount = defineStore("account", { hasInjector({ injector }): boolean { return injector != null; }, + hasSessionProxyForRole({ + sessionProxies, + }): (role: SessionProxyRole) => boolean { + return (role: SessionProxyRole): boolean => { + return sessionProxies[role] != null; + }; + }, + hasDeclinedSessionProxy({ sessionProxyDeclined }): boolean { + return sessionProxyDeclined; + }, + /// Returns the weakest session proxy which is authorized for at least the requested role + sessionProxyForRole({ + sessionProxies, + }): (role: SessionProxyRole) => AddressOrPair | null { + return (role: SessionProxyRole): AddressOrPair | null => { + const startIndex = sessionProxyRoleOrder.indexOf(role); + if (startIndex === -1) return null; + for (let i = startIndex; i < sessionProxyRoleOrder.length; i++) { + const currentRole = sessionProxyRoleOrder[i]; + if (sessionProxies[currentRole]) { + return sessionProxies[currentRole]; + } + } + return null; + }; + }, + /// Returns the most powerful session proxy + sessionProxyBest({ + sessionProxies, + }): () => [AddressOrPair | null, SessionProxyRole | null] { + return (): [AddressOrPair | null, SessionProxyRole | null] => { + for (let i = sessionProxyRoleOrder.length - 1; i >= 0; i--) { + const currentRole = sessionProxyRoleOrder[i]; + if (sessionProxies[currentRole]) { + return [sessionProxies[currentRole], currentRole]; + } + } + return [null, null]; + }; + }, + sessionProxySeed({ + sessionProxySeeds, + }): (proxy: AddressOrPair) => Uint8Array { + return (proxy: AddressOrPair): Uint8Array => { + return sessionProxySeeds[proxy]; + }; + }, formatBalanceFree({ balanceFree, decimals }) { return (chain: ChainId): string => { if (!balanceFree[chain]) return "0.000"; @@ -117,12 +174,33 @@ export const useAccount = defineStore("account", { }, }, actions: { + /// call this when account changes to clear all account-related state + resetState() { + this.sessionProxyDeclined = false; + this.sessionProxies = {}; + this.injector = null; + this.BalanceFree = {}; + this.BalanceReserved = {}; + this.BalanceFrozen = {}; + }, setAccount(account: AddressOrPair) { this.account = account; }, setInjector(injector: InjectedExtension) { this.injector = injector; }, + /// sticky decline for adding session proxies + declineSessionProxy() { + this.sessionProxyDeclined = true; + }, + addSessionProxy( + sessionProxy: AddressOrPair, + seed: Uint8Array, + role: SessionProxyRole, + ) { + this.sessionProxies[role] = sessionProxy; + this.sessionProxySeeds[sessionProxy] = seed; + }, setBalanceFree(balance: BigInt, chain: ChainId) { this.balanceFree[chain] = balance; }, diff --git a/store/notes.ts b/store/notes.ts index ce4e934..2e6737f 100644 --- a/store/notes.ts +++ b/store/notes.ts @@ -17,7 +17,10 @@ export const useNotes = defineStore("notes", { }, getFinancialNotes() { return this.getSortedNotesNewestFirst.filter( - (note) => (note.amount > 0) | note.category.includes("Guess"), + (note) => + (note.amount > 0) | + note.category.includes("Guess") | + note.category.includes("Session Proxy"), ); }, getConversationCounterparties() { diff --git a/yarn.lock b/yarn.lock index 2d55e21..900f629 100644 --- a/yarn.lock +++ b/yarn.lock @@ -531,32 +531,32 @@ __metadata: languageName: node linkType: hard -"@encointer/node-api@npm:^0.18.0-alpha.2": - version: 0.18.0-alpha.2 - resolution: "@encointer/node-api@npm:0.18.0-alpha.2" +"@encointer/node-api@npm:^0.18.0": + version: 0.18.0 + resolution: "@encointer/node-api@npm:0.18.0" dependencies: - "@encointer/types": "npm:^0.18.0-alpha.2" + "@encointer/types": "npm:^0.18.0" "@polkadot/api": "npm:^11.2.1" tslib: "npm:^2.6.2" - checksum: 10c0/383ac0109d83e5b908e0a33c648dee678773a674b86234f03f0694f5de7d370dac20bcde45f49335a2e5ddbfcd7ed62422fe8528b00cc7a9cd1acecae57616b3 + checksum: 10c0/e9cbf01b15a622b5d4a5c1b30e0257ce3d5aaeb5decf9aee05f6cc9c178c36b3efe1bf454422becf0150f86eedbc4f12948387e01e3e6e0a7489d8e3eb9c50e9 languageName: node linkType: hard -"@encointer/types@npm:^0.18.0-alpha.2": - version: 0.18.0-alpha.2 - resolution: "@encointer/types@npm:0.18.0-alpha.2" +"@encointer/types@npm:^0.18.0": + version: 0.18.0 + resolution: "@encointer/types@npm:0.18.0" dependencies: "@polkadot/api": "npm:^11.2.1" "@polkadot/types": "npm:^11.2.1" "@polkadot/types-codec": "npm:^11.2.1" "@polkadot/util": "npm:^12.6.2" - checksum: 10c0/dc4ba196329103de0cd3326f0d72eefee57b1dc347ceb59dfbac37828cb837c47a581bad10b4b483b7536fb5a8fd8a29fe055862a70092703507ab9169b528ac + checksum: 10c0/6001f1c4f76e55013e685c3b0ecb3da5cede271450e115974fbe2df68ccd868f9b2b67947e3bb38a8072e4666020c9cb394c9887f15be28fae6ec1b9b44add90 languageName: node linkType: hard -"@encointer/util@npm:^0.18.0-alpha.2": - version: 0.18.0-alpha.2 - resolution: "@encointer/util@npm:0.18.0-alpha.2" +"@encointer/util@npm:^0.18.0": + version: 0.18.0 + resolution: "@encointer/util@npm:0.18.0" dependencies: "@babel/runtime": "npm:^7.18.9" "@polkadot/util": "npm:^12.6.2" @@ -564,17 +564,17 @@ __metadata: "@types/bn.js": "npm:^5.1.5" assert: "npm:^2.0.0" bn.js: "npm:^5.2.1" - checksum: 10c0/128a8b3835afd403cace1de6ea102bdfd88c64e3a360ea09ccfeeb513c365d978699d44110f3a2ff4b5197594ea1065bb3a179c1cc0774ba6d89ed983ebec95f + checksum: 10c0/ad51ce72bb6acca6313f18fd02b33fc6365806b779c8acc653dc784ee9d6661a90d332aac0188e7afc0c0076daaf36ca7fde4ba9b917bfa09c8cdf376925a1cc languageName: node linkType: hard -"@encointer/worker-api@npm:^0.18.0-alpha.2": - version: 0.18.0-alpha.2 - resolution: "@encointer/worker-api@npm:0.18.0-alpha.2" +"@encointer/worker-api@npm:^0.18.0": + version: 0.18.0 + resolution: "@encointer/worker-api@npm:0.18.0" dependencies: - "@encointer/node-api": "npm:^0.18.0-alpha.2" - "@encointer/types": "npm:^0.18.0-alpha.2" - "@encointer/util": "npm:^0.18.0-alpha.2" + "@encointer/node-api": "npm:^0.18.0" + "@encointer/types": "npm:^0.18.0" + "@encointer/util": "npm:^0.18.0" "@peculiar/webcrypto": "npm:^1.4.6" "@polkadot/api": "npm:^11.2.1" "@polkadot/keyring": "npm:^12.6.2" @@ -589,7 +589,7 @@ __metadata: tslib: "npm:^2.6.2" peerDependencies: "@polkadot/x-randomvalues": ^12.3.2 - checksum: 10c0/3d2f835527d75c6b1b31550c0e7dbaeb98c97248d2bffc6b766fea8ac219d52e50ed57832c44a77c07f9e055c3eb7cf6f93a6cb14f27ba33600e9d5113df7b17 + checksum: 10c0/0c0332ff48f3e11b47817d6eff9e8b1bf75ec1c014e350f65733390a72fe92da6c750a1d43a3ddc2c6f87bc2a7f2403feaf0dd3fcd70a72a6ef44c5f41a3c1ee languageName: node linkType: hard @@ -10006,8 +10006,8 @@ __metadata: version: 0.0.0-use.local resolution: "nuxt-app@workspace:." dependencies: - "@encointer/util": "npm:^0.18.0-alpha.2" - "@encointer/worker-api": "npm:^0.18.0-alpha.2" + "@encointer/util": "npm:^0.18.0" + "@encointer/worker-api": "npm:^0.18.0" "@esbuild-plugins/node-globals-polyfill": "npm:^0.2.3" "@headlessui/vue": "npm:^1.7.22" "@heroicons/vue": "npm:^2.1.3"