From 8f68d46672a5a3c476e1f12bd2312ffece1a8b2a Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Tue, 31 May 2022 22:13:18 +0300 Subject: [PATCH 01/20] Fix(DelVestAcc): Route exceptions to ledger REST API [DEV-1388] --- src/api/bigDipperApi.ts | 2 +- src/api/nodeApi.ts | 2 +- src/handlers/circulatingSupply.ts | 16 ++++++++++++---- src/handlers/totalBalance.ts | 2 +- src/helpers/node.ts | 19 ++++++++++++------- src/helpers/validate.ts | 15 +++++++++++++++ src/types/node.ts | 13 ++++--------- 7 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/api/bigDipperApi.ts b/src/api/bigDipperApi.ts index c3259c4a..2546bf1d 100644 --- a/src/api/bigDipperApi.ts +++ b/src/api/bigDipperApi.ts @@ -39,7 +39,7 @@ export class BigDipperApi { return resp.account; } - async get_acocunt(address: string): Promise { + async get_account(address: string): Promise { let accounts = await this.get_accounts([address]); return accounts[0]; } diff --git a/src/api/nodeApi.ts b/src/api/nodeApi.ts index 88dfa8ff..f0001dcb 100644 --- a/src/api/nodeApi.ts +++ b/src/api/nodeApi.ts @@ -13,7 +13,7 @@ export class NodeApi { } async auth_get_account(address: string): Promise { - let resp = await fetch(`${this.base_rest_api_url}/cosmos/auth/v1beta1/accounts/${address}`); + let resp = await fetch(`${this.base_rest_api_url}/cosmos/auth/v1beta1/accounts/${address}`) let respJson = await resp.json() as { account: Account }; return respJson.account; diff --git a/src/handlers/circulatingSupply.ts b/src/handlers/circulatingSupply.ts index 97a92560..3a93ce81 100644 --- a/src/handlers/circulatingSupply.ts +++ b/src/handlers/circulatingSupply.ts @@ -1,18 +1,26 @@ import { GraphQLClient } from "../helpers/graphql"; import { BigDipperApi } from "../api/bigDipperApi"; +import { NodeApi } from '../api/nodeApi' import { Request } from "itty-router"; import { ncheq_to_cheq_fixed } from "../helpers/currency"; -import { total_balance_ncheq } from "../helpers/node"; +import { delayed_balance_ncheq, total_balance_ncheq } from "../helpers/node"; +import { filter_marked_as_account_types } from '../helpers/validate'; async function get_circulating_supply(circulating_supply_watchlist: string[]): Promise { let gql_client = new GraphQLClient(GRAPHQL_API); let bd_api = new BigDipperApi(gql_client); + let node_api = new NodeApi(REST_API); - let non_circulating_accounts = await bd_api.get_accounts(circulating_supply_watchlist); + let filtered_accounts = filter_marked_as_account_types(circulating_supply_watchlist); + + let non_circulating_accounts = await bd_api.get_accounts(filtered_accounts.other); + + let non_circulating_accounts_delayed = await Promise.all(filtered_accounts?.delayed?.map(address => node_api.auth_get_account(address))); // Calculate total balance of watchlist accounts let non_circulating_supply_ncheq = non_circulating_accounts.map(total_balance_ncheq).reduce((a, b) => a + b, 0); - console.log(`Non-circulating supply: ${non_circulating_supply_ncheq}`); + let non_circulating_supply_delayed_ncheq = non_circulating_accounts_delayed.map(account => delayed_balance_ncheq(account)).reduce((a, b) => a + b, 0); + console.log(`Non-circulating supply: ${non_circulating_supply_ncheq + non_circulating_supply_delayed_ncheq}`); // Get total supply let total_supply = await bd_api.get_total_supply(); @@ -20,7 +28,7 @@ async function get_circulating_supply(circulating_supply_watchlist: string[]): P console.log(`Total supply: ${total_supply_ncheq}`); // Calculate circulating supply - return total_supply_ncheq - non_circulating_supply_ncheq; + return total_supply_ncheq - non_circulating_supply_ncheq - non_circulating_supply_delayed_ncheq; } export async function handler(request: Request): Promise { diff --git a/src/handlers/totalBalance.ts b/src/handlers/totalBalance.ts index 263fefe8..99d67e37 100644 --- a/src/handlers/totalBalance.ts +++ b/src/handlers/totalBalance.ts @@ -15,7 +15,7 @@ export async function handler(request: Request): Promise { let gql_client = new GraphQLClient(GRAPHQL_API); let bd_api = new BigDipperApi(gql_client); - let account = await bd_api.get_acocunt(address); + let account = await bd_api.get_account(address); let balance = total_balance_ncheq(account); return new Response(ncheq_to_cheq_fixed(balance)) diff --git a/src/helpers/node.ts b/src/helpers/node.ts index 663ab09c..60560378 100644 --- a/src/helpers/node.ts +++ b/src/helpers/node.ts @@ -1,23 +1,28 @@ import { Account } from "../types/bigDipper"; +import { Account as AccountCosmos } from "../types/node"; export function total_balance_ncheq(account: Account): number { - let balance = Number(account.accountBalances[0]?.coins.find(c => c.denom === "ncheq")?.amount || '0'); + let balance = Number(account?.accountBalances[0]?.coins.find(c => c.denom === "ncheq")?.amount || '0'); - let delegations = account.delegations.map(d => d.amount) + let delegations = account?.delegations?.map(d => d.amount) .filter(a => a.denom === "ncheq") .map(a => Number(a.amount)) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a + b, 0) ?? 0; - let unbonding = account.unbonding.map(d => d.amount) + let unbonding = account?.unbonding?.map(d => d.amount) .filter(a => a.denom === "ncheq") .map(a => Number(a.amount)) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a + b, 0) ?? 0; - let rewards = account.delegationRewards.map(d => d.amount) + let rewards = account?.delegationRewards?.map(d => d.amount) .flat() .filter(a => a.denom === "ncheq") .map(a => Number(a.amount)) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a + b, 0) ?? 0; return balance + delegations + unbonding + rewards; } + +export function delayed_balance_ncheq(account: AccountCosmos): number { + return Number(account?.base_vesting_account.original_vesting.find(c => c.denom === "ncheq")?.amount || '0'); +} diff --git a/src/helpers/validate.ts b/src/helpers/validate.ts index d3618a9b..a00579de 100644 --- a/src/helpers/validate.ts +++ b/src/helpers/validate.ts @@ -5,4 +5,19 @@ export function validate_cheqd_address(address: string): boolean { export function is_vesting_account_type(account_type: string): boolean { return account_type === '/cosmos.vesting.v1beta1.ContinuousVestingAccount'; +} + +export function is_delayed_vesting_account_type(account_type: string): boolean { + return account_type === '/cosmos.vesting.v1beta1.DelayedVestingAccount'; +} + +export function marked_as_delayed_vesting_account(address: string): boolean { + return /^delayed:/.test(address); +} + +export function filter_marked_as_account_types(addresses: string[]): Record { + return { + delayed: addresses.filter(address => marked_as_delayed_vesting_account(address)).map(address => address.replace('delayed:', '')), + other: addresses.filter(address => !marked_as_delayed_vesting_account(address)).map(address => address) + }; } \ No newline at end of file diff --git a/src/types/node.ts b/src/types/node.ts index f76fa44c..936fc229 100644 --- a/src/types/node.ts +++ b/src/types/node.ts @@ -1,12 +1,7 @@ -export class Account { - public '@type': string; - public start_time: number; - public base_vesting_account: { original_vesting: Coin[], end_time: number }; - - constructor(start_time: number, base_vesting_account: { original_vesting: Coin[], end_time: number }) { - this.start_time = start_time; - this.base_vesting_account = base_vesting_account; - } +export type Account ={ + '@type': string; + start_time: number; + base_vesting_account: { original_vesting: Coin[], end_time: number }; } export class Coin { From 4b79f62b76441beac7241a9d025115ee929880f6 Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Tue, 31 May 2022 22:13:18 +0300 Subject: [PATCH 02/20] fix(del_vesting_acc): Route exceptions to ledger REST API [DEV-1388] --- src/api/bigDipperApi.ts | 2 +- src/api/nodeApi.ts | 2 +- src/handlers/circulatingSupply.ts | 16 ++++++++++++---- src/handlers/totalBalance.ts | 2 +- src/helpers/node.ts | 19 ++++++++++++------- src/helpers/validate.ts | 15 +++++++++++++++ src/types/node.ts | 13 ++++--------- 7 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/api/bigDipperApi.ts b/src/api/bigDipperApi.ts index c3259c4a..2546bf1d 100644 --- a/src/api/bigDipperApi.ts +++ b/src/api/bigDipperApi.ts @@ -39,7 +39,7 @@ export class BigDipperApi { return resp.account; } - async get_acocunt(address: string): Promise { + async get_account(address: string): Promise { let accounts = await this.get_accounts([address]); return accounts[0]; } diff --git a/src/api/nodeApi.ts b/src/api/nodeApi.ts index 88dfa8ff..f0001dcb 100644 --- a/src/api/nodeApi.ts +++ b/src/api/nodeApi.ts @@ -13,7 +13,7 @@ export class NodeApi { } async auth_get_account(address: string): Promise { - let resp = await fetch(`${this.base_rest_api_url}/cosmos/auth/v1beta1/accounts/${address}`); + let resp = await fetch(`${this.base_rest_api_url}/cosmos/auth/v1beta1/accounts/${address}`) let respJson = await resp.json() as { account: Account }; return respJson.account; diff --git a/src/handlers/circulatingSupply.ts b/src/handlers/circulatingSupply.ts index 97a92560..3a93ce81 100644 --- a/src/handlers/circulatingSupply.ts +++ b/src/handlers/circulatingSupply.ts @@ -1,18 +1,26 @@ import { GraphQLClient } from "../helpers/graphql"; import { BigDipperApi } from "../api/bigDipperApi"; +import { NodeApi } from '../api/nodeApi' import { Request } from "itty-router"; import { ncheq_to_cheq_fixed } from "../helpers/currency"; -import { total_balance_ncheq } from "../helpers/node"; +import { delayed_balance_ncheq, total_balance_ncheq } from "../helpers/node"; +import { filter_marked_as_account_types } from '../helpers/validate'; async function get_circulating_supply(circulating_supply_watchlist: string[]): Promise { let gql_client = new GraphQLClient(GRAPHQL_API); let bd_api = new BigDipperApi(gql_client); + let node_api = new NodeApi(REST_API); - let non_circulating_accounts = await bd_api.get_accounts(circulating_supply_watchlist); + let filtered_accounts = filter_marked_as_account_types(circulating_supply_watchlist); + + let non_circulating_accounts = await bd_api.get_accounts(filtered_accounts.other); + + let non_circulating_accounts_delayed = await Promise.all(filtered_accounts?.delayed?.map(address => node_api.auth_get_account(address))); // Calculate total balance of watchlist accounts let non_circulating_supply_ncheq = non_circulating_accounts.map(total_balance_ncheq).reduce((a, b) => a + b, 0); - console.log(`Non-circulating supply: ${non_circulating_supply_ncheq}`); + let non_circulating_supply_delayed_ncheq = non_circulating_accounts_delayed.map(account => delayed_balance_ncheq(account)).reduce((a, b) => a + b, 0); + console.log(`Non-circulating supply: ${non_circulating_supply_ncheq + non_circulating_supply_delayed_ncheq}`); // Get total supply let total_supply = await bd_api.get_total_supply(); @@ -20,7 +28,7 @@ async function get_circulating_supply(circulating_supply_watchlist: string[]): P console.log(`Total supply: ${total_supply_ncheq}`); // Calculate circulating supply - return total_supply_ncheq - non_circulating_supply_ncheq; + return total_supply_ncheq - non_circulating_supply_ncheq - non_circulating_supply_delayed_ncheq; } export async function handler(request: Request): Promise { diff --git a/src/handlers/totalBalance.ts b/src/handlers/totalBalance.ts index 263fefe8..99d67e37 100644 --- a/src/handlers/totalBalance.ts +++ b/src/handlers/totalBalance.ts @@ -15,7 +15,7 @@ export async function handler(request: Request): Promise { let gql_client = new GraphQLClient(GRAPHQL_API); let bd_api = new BigDipperApi(gql_client); - let account = await bd_api.get_acocunt(address); + let account = await bd_api.get_account(address); let balance = total_balance_ncheq(account); return new Response(ncheq_to_cheq_fixed(balance)) diff --git a/src/helpers/node.ts b/src/helpers/node.ts index 663ab09c..60560378 100644 --- a/src/helpers/node.ts +++ b/src/helpers/node.ts @@ -1,23 +1,28 @@ import { Account } from "../types/bigDipper"; +import { Account as AccountCosmos } from "../types/node"; export function total_balance_ncheq(account: Account): number { - let balance = Number(account.accountBalances[0]?.coins.find(c => c.denom === "ncheq")?.amount || '0'); + let balance = Number(account?.accountBalances[0]?.coins.find(c => c.denom === "ncheq")?.amount || '0'); - let delegations = account.delegations.map(d => d.amount) + let delegations = account?.delegations?.map(d => d.amount) .filter(a => a.denom === "ncheq") .map(a => Number(a.amount)) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a + b, 0) ?? 0; - let unbonding = account.unbonding.map(d => d.amount) + let unbonding = account?.unbonding?.map(d => d.amount) .filter(a => a.denom === "ncheq") .map(a => Number(a.amount)) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a + b, 0) ?? 0; - let rewards = account.delegationRewards.map(d => d.amount) + let rewards = account?.delegationRewards?.map(d => d.amount) .flat() .filter(a => a.denom === "ncheq") .map(a => Number(a.amount)) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a + b, 0) ?? 0; return balance + delegations + unbonding + rewards; } + +export function delayed_balance_ncheq(account: AccountCosmos): number { + return Number(account?.base_vesting_account.original_vesting.find(c => c.denom === "ncheq")?.amount || '0'); +} diff --git a/src/helpers/validate.ts b/src/helpers/validate.ts index d3618a9b..a00579de 100644 --- a/src/helpers/validate.ts +++ b/src/helpers/validate.ts @@ -5,4 +5,19 @@ export function validate_cheqd_address(address: string): boolean { export function is_vesting_account_type(account_type: string): boolean { return account_type === '/cosmos.vesting.v1beta1.ContinuousVestingAccount'; +} + +export function is_delayed_vesting_account_type(account_type: string): boolean { + return account_type === '/cosmos.vesting.v1beta1.DelayedVestingAccount'; +} + +export function marked_as_delayed_vesting_account(address: string): boolean { + return /^delayed:/.test(address); +} + +export function filter_marked_as_account_types(addresses: string[]): Record { + return { + delayed: addresses.filter(address => marked_as_delayed_vesting_account(address)).map(address => address.replace('delayed:', '')), + other: addresses.filter(address => !marked_as_delayed_vesting_account(address)).map(address => address) + }; } \ No newline at end of file diff --git a/src/types/node.ts b/src/types/node.ts index f76fa44c..936fc229 100644 --- a/src/types/node.ts +++ b/src/types/node.ts @@ -1,12 +1,7 @@ -export class Account { - public '@type': string; - public start_time: number; - public base_vesting_account: { original_vesting: Coin[], end_time: number }; - - constructor(start_time: number, base_vesting_account: { original_vesting: Coin[], end_time: number }) { - this.start_time = start_time; - this.base_vesting_account = base_vesting_account; - } +export type Account ={ + '@type': string; + start_time: number; + base_vesting_account: { original_vesting: Coin[], end_time: number }; } export class Coin { From 4799619807b27a8e2835d2aff3d8802c1958c5ce Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Tue, 31 May 2022 22:13:18 +0300 Subject: [PATCH 03/20] fix(del_vesting_acc): Route exceptions to ledger REST API [DEV-1388] --- src/api/bigDipperApi.ts | 2 +- src/api/nodeApi.ts | 2 +- src/handlers/circulatingSupply.ts | 16 ++++++++++++---- src/handlers/totalBalance.ts | 2 +- src/helpers/node.ts | 19 ++++++++++++------- src/helpers/validate.ts | 15 +++++++++++++++ src/types/node.ts | 13 ++++--------- 7 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/api/bigDipperApi.ts b/src/api/bigDipperApi.ts index c3259c4a..2546bf1d 100644 --- a/src/api/bigDipperApi.ts +++ b/src/api/bigDipperApi.ts @@ -39,7 +39,7 @@ export class BigDipperApi { return resp.account; } - async get_acocunt(address: string): Promise { + async get_account(address: string): Promise { let accounts = await this.get_accounts([address]); return accounts[0]; } diff --git a/src/api/nodeApi.ts b/src/api/nodeApi.ts index 88dfa8ff..f0001dcb 100644 --- a/src/api/nodeApi.ts +++ b/src/api/nodeApi.ts @@ -13,7 +13,7 @@ export class NodeApi { } async auth_get_account(address: string): Promise { - let resp = await fetch(`${this.base_rest_api_url}/cosmos/auth/v1beta1/accounts/${address}`); + let resp = await fetch(`${this.base_rest_api_url}/cosmos/auth/v1beta1/accounts/${address}`) let respJson = await resp.json() as { account: Account }; return respJson.account; diff --git a/src/handlers/circulatingSupply.ts b/src/handlers/circulatingSupply.ts index 97a92560..3a93ce81 100644 --- a/src/handlers/circulatingSupply.ts +++ b/src/handlers/circulatingSupply.ts @@ -1,18 +1,26 @@ import { GraphQLClient } from "../helpers/graphql"; import { BigDipperApi } from "../api/bigDipperApi"; +import { NodeApi } from '../api/nodeApi' import { Request } from "itty-router"; import { ncheq_to_cheq_fixed } from "../helpers/currency"; -import { total_balance_ncheq } from "../helpers/node"; +import { delayed_balance_ncheq, total_balance_ncheq } from "../helpers/node"; +import { filter_marked_as_account_types } from '../helpers/validate'; async function get_circulating_supply(circulating_supply_watchlist: string[]): Promise { let gql_client = new GraphQLClient(GRAPHQL_API); let bd_api = new BigDipperApi(gql_client); + let node_api = new NodeApi(REST_API); - let non_circulating_accounts = await bd_api.get_accounts(circulating_supply_watchlist); + let filtered_accounts = filter_marked_as_account_types(circulating_supply_watchlist); + + let non_circulating_accounts = await bd_api.get_accounts(filtered_accounts.other); + + let non_circulating_accounts_delayed = await Promise.all(filtered_accounts?.delayed?.map(address => node_api.auth_get_account(address))); // Calculate total balance of watchlist accounts let non_circulating_supply_ncheq = non_circulating_accounts.map(total_balance_ncheq).reduce((a, b) => a + b, 0); - console.log(`Non-circulating supply: ${non_circulating_supply_ncheq}`); + let non_circulating_supply_delayed_ncheq = non_circulating_accounts_delayed.map(account => delayed_balance_ncheq(account)).reduce((a, b) => a + b, 0); + console.log(`Non-circulating supply: ${non_circulating_supply_ncheq + non_circulating_supply_delayed_ncheq}`); // Get total supply let total_supply = await bd_api.get_total_supply(); @@ -20,7 +28,7 @@ async function get_circulating_supply(circulating_supply_watchlist: string[]): P console.log(`Total supply: ${total_supply_ncheq}`); // Calculate circulating supply - return total_supply_ncheq - non_circulating_supply_ncheq; + return total_supply_ncheq - non_circulating_supply_ncheq - non_circulating_supply_delayed_ncheq; } export async function handler(request: Request): Promise { diff --git a/src/handlers/totalBalance.ts b/src/handlers/totalBalance.ts index 263fefe8..99d67e37 100644 --- a/src/handlers/totalBalance.ts +++ b/src/handlers/totalBalance.ts @@ -15,7 +15,7 @@ export async function handler(request: Request): Promise { let gql_client = new GraphQLClient(GRAPHQL_API); let bd_api = new BigDipperApi(gql_client); - let account = await bd_api.get_acocunt(address); + let account = await bd_api.get_account(address); let balance = total_balance_ncheq(account); return new Response(ncheq_to_cheq_fixed(balance)) diff --git a/src/helpers/node.ts b/src/helpers/node.ts index 663ab09c..60560378 100644 --- a/src/helpers/node.ts +++ b/src/helpers/node.ts @@ -1,23 +1,28 @@ import { Account } from "../types/bigDipper"; +import { Account as AccountCosmos } from "../types/node"; export function total_balance_ncheq(account: Account): number { - let balance = Number(account.accountBalances[0]?.coins.find(c => c.denom === "ncheq")?.amount || '0'); + let balance = Number(account?.accountBalances[0]?.coins.find(c => c.denom === "ncheq")?.amount || '0'); - let delegations = account.delegations.map(d => d.amount) + let delegations = account?.delegations?.map(d => d.amount) .filter(a => a.denom === "ncheq") .map(a => Number(a.amount)) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a + b, 0) ?? 0; - let unbonding = account.unbonding.map(d => d.amount) + let unbonding = account?.unbonding?.map(d => d.amount) .filter(a => a.denom === "ncheq") .map(a => Number(a.amount)) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a + b, 0) ?? 0; - let rewards = account.delegationRewards.map(d => d.amount) + let rewards = account?.delegationRewards?.map(d => d.amount) .flat() .filter(a => a.denom === "ncheq") .map(a => Number(a.amount)) - .reduce((a, b) => a + b, 0); + .reduce((a, b) => a + b, 0) ?? 0; return balance + delegations + unbonding + rewards; } + +export function delayed_balance_ncheq(account: AccountCosmos): number { + return Number(account?.base_vesting_account.original_vesting.find(c => c.denom === "ncheq")?.amount || '0'); +} diff --git a/src/helpers/validate.ts b/src/helpers/validate.ts index d3618a9b..a00579de 100644 --- a/src/helpers/validate.ts +++ b/src/helpers/validate.ts @@ -5,4 +5,19 @@ export function validate_cheqd_address(address: string): boolean { export function is_vesting_account_type(account_type: string): boolean { return account_type === '/cosmos.vesting.v1beta1.ContinuousVestingAccount'; +} + +export function is_delayed_vesting_account_type(account_type: string): boolean { + return account_type === '/cosmos.vesting.v1beta1.DelayedVestingAccount'; +} + +export function marked_as_delayed_vesting_account(address: string): boolean { + return /^delayed:/.test(address); +} + +export function filter_marked_as_account_types(addresses: string[]): Record { + return { + delayed: addresses.filter(address => marked_as_delayed_vesting_account(address)).map(address => address.replace('delayed:', '')), + other: addresses.filter(address => !marked_as_delayed_vesting_account(address)).map(address => address) + }; } \ No newline at end of file diff --git a/src/types/node.ts b/src/types/node.ts index f76fa44c..936fc229 100644 --- a/src/types/node.ts +++ b/src/types/node.ts @@ -1,12 +1,7 @@ -export class Account { - public '@type': string; - public start_time: number; - public base_vesting_account: { original_vesting: Coin[], end_time: number }; - - constructor(start_time: number, base_vesting_account: { original_vesting: Coin[], end_time: number }) { - this.start_time = start_time; - this.base_vesting_account = base_vesting_account; - } +export type Account ={ + '@type': string; + start_time: number; + base_vesting_account: { original_vesting: Coin[], end_time: number }; } export class Coin { From 2c958e1c549ade2eddb8ef31229781a7fb1ae7e4 Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Wed, 1 Jun 2022 14:38:20 +0300 Subject: [PATCH 04/20] Added REST API DelayedVesting account singular address balance support --- src/api/nodeApi.ts | 16 +++++++++++++++- src/handlers/totalBalance.ts | 14 +++++++++++++- src/helpers/validate.ts | 2 +- src/helpers/vesting.ts | 2 ++ src/types/node.ts | 2 +- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/api/nodeApi.ts b/src/api/nodeApi.ts index f0001dcb..70cc7dfe 100644 --- a/src/api/nodeApi.ts +++ b/src/api/nodeApi.ts @@ -1,4 +1,4 @@ -import { Account } from "../types/node"; +import { Account, Coin } from "../types/node"; export class NodeApi { @@ -18,4 +18,18 @@ export class NodeApi { return respJson.account; } + + async bank_get_account_balances(address: string): Promise { + let resp = await fetch(`${this.base_rest_api_url}/cosmos/bank/v1beta1/balances/${address}`) + let respJson = await resp.json() as { balances: Coin[] }; + + return respJson.balances; + } + + async distribution_get_total_rewards(address: string): Promise { + let resp = await fetch(`${this.base_rest_api_url}/cosmos/distribution/v1beta1/delegators/${address}/rewards`) + let respJson = await resp.json() as { rewards: Record[], total: Coin[] }; + + return Number(respJson?.total?.[0]?.amount ?? '0'); + } } diff --git a/src/handlers/totalBalance.ts b/src/handlers/totalBalance.ts index 99d67e37..680e7d43 100644 --- a/src/handlers/totalBalance.ts +++ b/src/handlers/totalBalance.ts @@ -1,9 +1,10 @@ import { Request } from "itty-router"; -import { validate_cheqd_address} from "../helpers/validate"; +import { is_delayed_vesting_account_type, validate_cheqd_address} from "../helpers/validate"; import { ncheq_to_cheq_fixed } from "../helpers/currency"; import { BigDipperApi } from "../api/bigDipperApi"; import { GraphQLClient } from "../helpers/graphql"; import { total_balance_ncheq } from "../helpers/node"; +import { NodeApi } from "../api/nodeApi"; export async function handler(request: Request): Promise { const address = request.params?.['address']; @@ -12,6 +13,17 @@ export async function handler(request: Request): Promise { throw new Error("No address specified or wrong address format."); } + let node_api = new NodeApi(REST_API); + let auth_account = await node_api.auth_get_account(address); + + if(is_delayed_vesting_account_type(auth_account?.["@type"])) { + let balance = Number(await (await node_api.bank_get_account_balances(address)).find(b => b.denom === "ncheq")?.amount) ?? 0; + let rewards = Number(await (await node_api.distribution_get_total_rewards(address))) ?? 0; + let delegated = Number(auth_account?.base_vesting_account?.delegated_vesting?.find(d => d.denom === "ncheq")?.amount) ?? 0; + + return new Response(ncheq_to_cheq_fixed(balance + rewards + delegated)); + } + let gql_client = new GraphQLClient(GRAPHQL_API); let bd_api = new BigDipperApi(gql_client); diff --git a/src/helpers/validate.ts b/src/helpers/validate.ts index a00579de..045bacf3 100644 --- a/src/helpers/validate.ts +++ b/src/helpers/validate.ts @@ -4,7 +4,7 @@ export function validate_cheqd_address(address: string): boolean { } export function is_vesting_account_type(account_type: string): boolean { - return account_type === '/cosmos.vesting.v1beta1.ContinuousVestingAccount'; + return account_type === '/cosmos.vesting.v1beta1.ContinuousVestingAccount' || account_type === '/cosmos.vesting.v1beta1.DelayedVestingAccount'; } export function is_delayed_vesting_account_type(account_type: string): boolean { diff --git a/src/helpers/vesting.ts b/src/helpers/vesting.ts index f7bf7415..1499e2ab 100644 --- a/src/helpers/vesting.ts +++ b/src/helpers/vesting.ts @@ -5,6 +5,8 @@ import { Account } from "../types/node"; // Here is the explanation of how to do it properly: // https://docs.cosmos.network/master/modules/auth/05_vesting.html#transferring-sending export function calculate_liquid_coins(account: Account): number { + if(account?.["@type"] === "/cosmos.vesting.v1beta1.DelayedVestingAccount") return 0 + const start_time = new Date(account.start_time * 1000).getTime(); const end_time = new Date(account.base_vesting_account.end_time * 1000).getTime(); const now = new Date().getTime(); diff --git a/src/types/node.ts b/src/types/node.ts index 936fc229..3c4e71b0 100644 --- a/src/types/node.ts +++ b/src/types/node.ts @@ -1,7 +1,7 @@ export type Account ={ '@type': string; start_time: number; - base_vesting_account: { original_vesting: Coin[], end_time: number }; + base_vesting_account: { original_vesting: Coin[], delegated_free?: Coin[], delegated_vesting?: Coin[], end_time: number }; } export class Coin { From 976a901dd20530db60e7819693c23bffbd151524 Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Wed, 1 Jun 2022 14:49:38 +0300 Subject: [PATCH 05/20] Slight fix on syntax for parsing --- src/handlers/totalBalance.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/handlers/totalBalance.ts b/src/handlers/totalBalance.ts index 680e7d43..9b17d0f8 100644 --- a/src/handlers/totalBalance.ts +++ b/src/handlers/totalBalance.ts @@ -17,9 +17,9 @@ export async function handler(request: Request): Promise { let auth_account = await node_api.auth_get_account(address); if(is_delayed_vesting_account_type(auth_account?.["@type"])) { - let balance = Number(await (await node_api.bank_get_account_balances(address)).find(b => b.denom === "ncheq")?.amount) ?? 0; - let rewards = Number(await (await node_api.distribution_get_total_rewards(address))) ?? 0; - let delegated = Number(auth_account?.base_vesting_account?.delegated_vesting?.find(d => d.denom === "ncheq")?.amount) ?? 0; + let balance = Number(await (await node_api.bank_get_account_balances(address)).find(b => b.denom === "ncheq")?.amount ?? '0'); + let rewards = Number(await (await node_api.distribution_get_total_rewards(address)) ?? '0'); + let delegated = Number(auth_account?.base_vesting_account?.delegated_vesting?.find(d => d.denom === "ncheq")?.amount ?? '0'); return new Response(ncheq_to_cheq_fixed(balance + rewards + delegated)); } From 4b1f064a7d110e21c6839961976350403e30ad14 Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Wed, 1 Jun 2022 15:08:35 +0300 Subject: [PATCH 06/20] Switched to full art path --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 77068763..bb79fde3 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,7 +32,7 @@ jobs: command: publish --env staging production-deploy: - if: ${{ success() }} && ( github.ref_name == 'main' ) + if: ${{ success() }} && ( github.ref == 'refs/heads/main' ) needs: staging-deploy name: "Cloudflare - Production" runs-on: ubuntu-latest From 836b470827648a13d1e7b5aea728941695e00cb7 Mon Sep 17 00:00:00 2001 From: Ankur Banerjee Date: Wed, 1 Jun 2022 13:09:05 +0100 Subject: [PATCH 07/20] Update deploy.yml --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 77068763..0e4917ad 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,7 +32,7 @@ jobs: command: publish --env staging production-deploy: - if: ${{ success() }} && ( github.ref_name == 'main' ) + if: ${{ success() }} && ( ${{ github.ref_name == 'main' }} ) needs: staging-deploy name: "Cloudflare - Production" runs-on: ubuntu-latest From e095a90976f863c3815867bb33abc1839f53d902 Mon Sep 17 00:00:00 2001 From: Ankur Banerjee Date: Wed, 1 Jun 2022 13:16:38 +0100 Subject: [PATCH 08/20] Update deploy.yml --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 0e4917ad..d3c7df5b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,9 +32,9 @@ jobs: command: publish --env staging production-deploy: - if: ${{ success() }} && ( ${{ github.ref_name == 'main' }} ) - needs: staging-deploy name: "Cloudflare - Production" + needs: staging-deploy + if: ${{ success() && ( github.ref_name == 'main' ) }} runs-on: ubuntu-latest permissions: security-events: write From 933596fffae490beebcc0b7b6dfbab719394a486 Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Wed, 1 Jun 2022 15:18:03 +0300 Subject: [PATCH 09/20] Checking separately --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index bb79fde3..1281a038 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,7 +32,7 @@ jobs: command: publish --env staging production-deploy: - if: ${{ success() }} && ( github.ref == 'refs/heads/main' ) + if: github.ref == 'refs/heads/main' needs: staging-deploy name: "Cloudflare - Production" runs-on: ubuntu-latest From fd6b0dc80b5435c91a5a3bcdbf92e4a17d0481e0 Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Wed, 1 Jun 2022 15:19:32 +0300 Subject: [PATCH 10/20] Added to expression --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 1281a038..8f33b66f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -32,7 +32,7 @@ jobs: command: publish --env staging production-deploy: - if: github.ref == 'refs/heads/main' + if: ${{ success() && ( github.ref == 'refs/heads/main' ) }} needs: staging-deploy name: "Cloudflare - Production" runs-on: ubuntu-latest From d9d5f1b56523e2354e5990f2ae21c98a8141888e Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Wed, 1 Jun 2022 18:35:42 +0300 Subject: [PATCH 11/20] Added actual liquid representation breakdown --- src/handlers/liquidBalance.ts | 10 +++++++++- src/helpers/vesting.ts | 2 +- src/types/node.ts | 14 +++++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/handlers/liquidBalance.ts b/src/handlers/liquidBalance.ts index c2401f55..33927383 100644 --- a/src/handlers/liquidBalance.ts +++ b/src/handlers/liquidBalance.ts @@ -1,5 +1,5 @@ import { Request } from "itty-router"; -import { is_vesting_account_type, validate_cheqd_address } from "../helpers/validate"; +import { is_delayed_vesting_account_type, is_vesting_account_type, validate_cheqd_address } from "../helpers/validate"; import { NodeApi } from "../api/nodeApi"; import { calculate_liquid_coins } from "../helpers/vesting"; import { ncheq_to_cheq_fixed } from "../helpers/currency"; @@ -18,6 +18,14 @@ export async function handler(request: Request): Promise { throw new Error(`Only vesting accounts are supported. Accounts type '${account["@type"]}'.`) } + if(is_delayed_vesting_account_type(account?.["@type"])) { + let balance = account?.base_vesting_account?.base_account?.sequence !== '0' ? Number(await (await api.bank_get_account_balances(address)).find(b => b.denom === "ncheq")?.amount ?? '0') : 0; + let rewards = Number(await (await api.distribution_get_total_rewards(address)) ?? '0'); + let delegated = Number(account?.base_vesting_account?.delegated_free?.find(d => d.denom === "ncheq")?.amount ?? '0'); + + return new Response(ncheq_to_cheq_fixed(balance + rewards + delegated)); + } + let liquid_coins = calculate_liquid_coins(account); return new Response(ncheq_to_cheq_fixed(liquid_coins)); diff --git a/src/helpers/vesting.ts b/src/helpers/vesting.ts index 1499e2ab..1a57f7c9 100644 --- a/src/helpers/vesting.ts +++ b/src/helpers/vesting.ts @@ -5,7 +5,7 @@ import { Account } from "../types/node"; // Here is the explanation of how to do it properly: // https://docs.cosmos.network/master/modules/auth/05_vesting.html#transferring-sending export function calculate_liquid_coins(account: Account): number { - if(account?.["@type"] === "/cosmos.vesting.v1beta1.DelayedVestingAccount") return 0 + if(account?.["@type"] === "/cosmos.vesting.v1beta1.DelayedVestingAccount" && (Date.now() < account?.base_vesting_account?.end_time * 1000) ) return 0 const start_time = new Date(account.start_time * 1000).getTime(); const end_time = new Date(account.base_vesting_account.end_time * 1000).getTime(); diff --git a/src/types/node.ts b/src/types/node.ts index 3c4e71b0..b451024f 100644 --- a/src/types/node.ts +++ b/src/types/node.ts @@ -1,7 +1,19 @@ export type Account ={ '@type': string; start_time: number; - base_vesting_account: { original_vesting: Coin[], delegated_free?: Coin[], delegated_vesting?: Coin[], end_time: number }; + base_vesting_account: { base_account: BaseAccount, original_vesting: Coin[], delegated_free?: Coin[], delegated_vesting?: Coin[], end_time: number }; +} + +export type BaseAccount = { + address: string; + pub_key: PublicKey; + account_number: string; + sequence: string; +} + +export type PublicKey = { + '@type': string; + key: string; } export class Coin { From bdfa816a197658bf7aaf53e9b5f12ffdd1ade84a Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Thu, 2 Jun 2022 18:16:52 +0300 Subject: [PATCH 12/20] Fixed liquid definitions & separate vested endpoint --- src/handlers/circulatingSupply.ts | 2 +- src/handlers/liquidBalance.ts | 7 +++++-- src/handlers/totalBalance.ts | 2 +- src/handlers/vestedBalance.ts | 24 ++++++++++++++++++++++++ src/helpers/validate.ts | 4 ++++ src/helpers/vesting.ts | 12 ++++++------ src/index.ts | 2 ++ 7 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 src/handlers/vestedBalance.ts diff --git a/src/handlers/circulatingSupply.ts b/src/handlers/circulatingSupply.ts index 3a93ce81..57b6c2df 100644 --- a/src/handlers/circulatingSupply.ts +++ b/src/handlers/circulatingSupply.ts @@ -1,6 +1,6 @@ import { GraphQLClient } from "../helpers/graphql"; import { BigDipperApi } from "../api/bigDipperApi"; -import { NodeApi } from '../api/nodeApi' +import { NodeApi } from '../api/nodeApi'; import { Request } from "itty-router"; import { ncheq_to_cheq_fixed } from "../helpers/currency"; import { delayed_balance_ncheq, total_balance_ncheq } from "../helpers/node"; diff --git a/src/handlers/liquidBalance.ts b/src/handlers/liquidBalance.ts index 33927383..a944ff8e 100644 --- a/src/handlers/liquidBalance.ts +++ b/src/handlers/liquidBalance.ts @@ -1,7 +1,7 @@ import { Request } from "itty-router"; import { is_delayed_vesting_account_type, is_vesting_account_type, validate_cheqd_address } from "../helpers/validate"; import { NodeApi } from "../api/nodeApi"; -import { calculate_liquid_coins } from "../helpers/vesting"; +import { calculate_vested_coins } from "../helpers/vesting"; import { ncheq_to_cheq_fixed } from "../helpers/currency"; export async function handler(request: Request): Promise { @@ -26,7 +26,10 @@ export async function handler(request: Request): Promise { return new Response(ncheq_to_cheq_fixed(balance + rewards + delegated)); } - let liquid_coins = calculate_liquid_coins(account); + let vested_coins = calculate_vested_coins(account); + let balance = Number(await (await api.bank_get_account_balances(address)).find(b => b.denom === "ncheq")?.amount ?? '0') + let rewards = Number(await (await api.distribution_get_total_rewards(address)) ?? '0'); + let liquid_coins = vested_coins + balance + rewards; return new Response(ncheq_to_cheq_fixed(liquid_coins)); } diff --git a/src/handlers/totalBalance.ts b/src/handlers/totalBalance.ts index 9b17d0f8..c1bc6afa 100644 --- a/src/handlers/totalBalance.ts +++ b/src/handlers/totalBalance.ts @@ -28,7 +28,7 @@ export async function handler(request: Request): Promise { let bd_api = new BigDipperApi(gql_client); let account = await bd_api.get_account(address); - let balance = total_balance_ncheq(account); + let balance = total_balance_ncheq(account); return new Response(ncheq_to_cheq_fixed(balance)) } diff --git a/src/handlers/vestedBalance.ts b/src/handlers/vestedBalance.ts new file mode 100644 index 00000000..14d08331 --- /dev/null +++ b/src/handlers/vestedBalance.ts @@ -0,0 +1,24 @@ +import { Request } from "itty-router"; +import { is_vesting_account_type, validate_cheqd_address } from "../helpers/validate"; +import { NodeApi } from "../api/nodeApi"; +import { calculate_vested_coins } from "../helpers/vesting"; +import { ncheq_to_cheq_fixed } from "../helpers/currency"; + +export async function handler(request: Request): Promise { + const address = request.params?.['address']; + + if (!address || !validate_cheqd_address(address)) { + throw new Error("No address specified or wrong address format."); + } + + let api = new NodeApi(REST_API); + const account = await api.auth_get_account(address); + + if (!is_vesting_account_type(account["@type"])) { + throw new Error(`Only vesting accounts are supported. Accounts type '${account["@type"]}'.`) + } + + let vested_coins = calculate_vested_coins(account); + + return new Response(ncheq_to_cheq_fixed(vested_coins)); +} diff --git a/src/helpers/validate.ts b/src/helpers/validate.ts index 045bacf3..58e8878a 100644 --- a/src/helpers/validate.ts +++ b/src/helpers/validate.ts @@ -7,6 +7,10 @@ export function is_vesting_account_type(account_type: string): boolean { return account_type === '/cosmos.vesting.v1beta1.ContinuousVestingAccount' || account_type === '/cosmos.vesting.v1beta1.DelayedVestingAccount'; } +export function is_continuous_vesting_account_type(account_type: string): boolean { + return account_type === '/cosmos.vesting.v1beta1.ContinuousVestingAccount'; +} + export function is_delayed_vesting_account_type(account_type: string): boolean { return account_type === '/cosmos.vesting.v1beta1.DelayedVestingAccount'; } diff --git a/src/helpers/vesting.ts b/src/helpers/vesting.ts index 1a57f7c9..b50e3b15 100644 --- a/src/helpers/vesting.ts +++ b/src/helpers/vesting.ts @@ -4,21 +4,21 @@ import { Account } from "../types/node"; // To calculate spendable tokens we need to take into account initial balance + sent and received tokens as well. // Here is the explanation of how to do it properly: // https://docs.cosmos.network/master/modules/auth/05_vesting.html#transferring-sending -export function calculate_liquid_coins(account: Account): number { +export function calculate_vested_coins(account: Account): number { if(account?.["@type"] === "/cosmos.vesting.v1beta1.DelayedVestingAccount" && (Date.now() < account?.base_vesting_account?.end_time * 1000) ) return 0 const start_time = new Date(account.start_time * 1000).getTime(); const end_time = new Date(account.base_vesting_account.end_time * 1000).getTime(); const now = new Date().getTime(); - const time_elapsed_in_days = Math.floor(Math.abs(now - start_time) / (1000 * 60 * 60 * 24)); - const time_vested_in_days = Math.floor(Math.abs(end_time - start_time) / (1000 * 60 * 60 * 24)); + const time_elapsed_in_days = Math.abs(now - start_time) / 1000; + const time_vested_in_days = Math.abs(end_time - start_time) / 1000; - const ratio = Number(time_elapsed_in_days / time_vested_in_days) + const ratio = Number(time_elapsed_in_days / time_vested_in_days); - return ratio * Number(account.base_vesting_account.original_vesting[0].amount) + return ratio * Number(account.base_vesting_account.original_vesting[0].amount); } export function calculate_vesting_coins(account: Account): number { - return Number(account.base_vesting_account.original_vesting[0].amount) - calculate_liquid_coins(account); + return Number(account.base_vesting_account.original_vesting[0].amount) - calculate_vested_coins(account); } diff --git a/src/index.ts b/src/index.ts index ad1d31c7..d25dc1e5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,6 +4,7 @@ import { handler as totalBalanceHandler } from "./handlers/totalBalance"; import { handler as circulatingSupplyHandler } from "./handlers/circulatingSupply"; import { handler as liquidBalanceHandler } from "./handlers/liquidBalance"; import { handler as vestingBalanceHandler } from "./handlers/vestingBalance"; +import { handler as vestedBalanceHandler } from "./handlers/vestedBalance"; addEventListener('fetch', (event: FetchEvent) => { const router = Router() @@ -19,6 +20,7 @@ function registerRoutes(router: Router) { router.get('/balances/total/:address', totalBalanceHandler); router.get('/balances/liquid/:address', liquidBalanceHandler); router.get('/balances/vesting/:address', vestingBalanceHandler); + router.get('/balances/vested/:address', vestedBalanceHandler); // 404 for all other requests router.all('*', () => new Response('Not Found.', {status: 404})) From 022bf4dbfae62b314830b065cd719561ec13e400 Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Thu, 2 Jun 2022 19:56:47 +0300 Subject: [PATCH 13/20] Added marking indicator --- .gitignore | 4 ++++ _/delayed/delayed.py | 26 ++++++++++++++++++++++++++ _/delayed/input/README.md | 4 ++++ _/delayed/output/README.md | 4 ++++ 4 files changed, 38 insertions(+) create mode 100644 _/delayed/delayed.py create mode 100644 _/delayed/input/README.md create mode 100644 _/delayed/output/README.md diff --git a/.gitignore b/.gitignore index dd811936..80602fa7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ ### APP-SPECIFIC EXCLUSIONS ### wrangler.dev.toml watchlist.json +_/delayed/input/* +!_/delayed/input/README.md +_/delayed/output/* +!_/delayed/output/README.md ### GENERAL EXCLUSIONS ### diff --git a/_/delayed/delayed.py b/_/delayed/delayed.py new file mode 100644 index 00000000..ec1cc5b6 --- /dev/null +++ b/_/delayed/delayed.py @@ -0,0 +1,26 @@ +import csv +import requests + +def main(): + input = [] + with open('./input/delayed.csv', 'r') as f: + reader = csv.reader(f) + for row in reader: + account = requests.get( + f'https://api.cheqd.net/cosmos/auth/v1beta1/accounts/{row[0]}', + headers={ + 'Content-Type': 'application/json', + } + ).json() + + if account.get('account', None) and account['account']['@type'] == '/cosmos.vesting.v1beta1.DelayedVestingAccount' and account['account']['base_vesting_account']['base_account']['sequence'] == '0': + input.append(row) + + if not input: print('No accounts found to be marked as delayed.\n'); exit(0) + + with open('./output/delayed.csv', 'w') as f: + writer = csv.writer(f, lineterminator='\n') + writer.writerows(input) + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/_/delayed/input/README.md b/_/delayed/input/README.md new file mode 100644 index 00000000..bdc81577 --- /dev/null +++ b/_/delayed/input/README.md @@ -0,0 +1,4 @@ +## Insert a csv of a single column of addresses, +# e.g. +# cheqd... +# cheqd.... \ No newline at end of file diff --git a/_/delayed/output/README.md b/_/delayed/output/README.md new file mode 100644 index 00000000..56db519d --- /dev/null +++ b/_/delayed/output/README.md @@ -0,0 +1,4 @@ +## Produces a csv of a single column of addresses that need to be marked as delayed, +# e.g. +# cheqd... +# cheqd.... \ No newline at end of file From dd5b21e21c0fe81ff760f9d2507aee1539a2669a Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Thu, 2 Jun 2022 20:03:31 +0300 Subject: [PATCH 14/20] Fixed markdowns --- _/delayed/input/README.md | 8 ++++---- _/delayed/output/README.md | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/_/delayed/input/README.md b/_/delayed/input/README.md index bdc81577..d4d06e3f 100644 --- a/_/delayed/input/README.md +++ b/_/delayed/input/README.md @@ -1,4 +1,4 @@ -## Insert a csv of a single column of addresses, -# e.g. -# cheqd... -# cheqd.... \ No newline at end of file +# Insert a csv of a single column of addresses +e.g. +`cheqd...` +`cheqd....` \ No newline at end of file diff --git a/_/delayed/output/README.md b/_/delayed/output/README.md index 56db519d..ca557744 100644 --- a/_/delayed/output/README.md +++ b/_/delayed/output/README.md @@ -1,4 +1,4 @@ -## Produces a csv of a single column of addresses that need to be marked as delayed, -# e.g. -# cheqd... -# cheqd.... \ No newline at end of file +# Produces a csv of a single column of addresses that need to be marked as delayed +e.g. +`cheqd...` +`cheqd....` \ No newline at end of file From 77344b176c416062f51633ea048d74c5763c1e8f Mon Sep 17 00:00:00 2001 From: Tasos <50984242+Eengineer1@users.noreply.github.com> Date: Thu, 2 Jun 2022 20:19:18 +0300 Subject: [PATCH 15/20] Switched to bank balances & removed helper --- .gitignore | 4 ---- _/delayed/delayed.py | 26 -------------------------- _/delayed/input/README.md | 4 ---- _/delayed/output/README.md | 4 ---- src/handlers/circulatingSupply.ts | 2 +- src/helpers/node.ts | 6 +++--- 6 files changed, 4 insertions(+), 42 deletions(-) delete mode 100644 _/delayed/delayed.py delete mode 100644 _/delayed/input/README.md delete mode 100644 _/delayed/output/README.md diff --git a/.gitignore b/.gitignore index 80602fa7..dd811936 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,6 @@ ### APP-SPECIFIC EXCLUSIONS ### wrangler.dev.toml watchlist.json -_/delayed/input/* -!_/delayed/input/README.md -_/delayed/output/* -!_/delayed/output/README.md ### GENERAL EXCLUSIONS ### diff --git a/_/delayed/delayed.py b/_/delayed/delayed.py deleted file mode 100644 index ec1cc5b6..00000000 --- a/_/delayed/delayed.py +++ /dev/null @@ -1,26 +0,0 @@ -import csv -import requests - -def main(): - input = [] - with open('./input/delayed.csv', 'r') as f: - reader = csv.reader(f) - for row in reader: - account = requests.get( - f'https://api.cheqd.net/cosmos/auth/v1beta1/accounts/{row[0]}', - headers={ - 'Content-Type': 'application/json', - } - ).json() - - if account.get('account', None) and account['account']['@type'] == '/cosmos.vesting.v1beta1.DelayedVestingAccount' and account['account']['base_vesting_account']['base_account']['sequence'] == '0': - input.append(row) - - if not input: print('No accounts found to be marked as delayed.\n'); exit(0) - - with open('./output/delayed.csv', 'w') as f: - writer = csv.writer(f, lineterminator='\n') - writer.writerows(input) - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/_/delayed/input/README.md b/_/delayed/input/README.md deleted file mode 100644 index d4d06e3f..00000000 --- a/_/delayed/input/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Insert a csv of a single column of addresses -e.g. -`cheqd...` -`cheqd....` \ No newline at end of file diff --git a/_/delayed/output/README.md b/_/delayed/output/README.md deleted file mode 100644 index ca557744..00000000 --- a/_/delayed/output/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Produces a csv of a single column of addresses that need to be marked as delayed -e.g. -`cheqd...` -`cheqd....` \ No newline at end of file diff --git a/src/handlers/circulatingSupply.ts b/src/handlers/circulatingSupply.ts index 57b6c2df..e14fd05e 100644 --- a/src/handlers/circulatingSupply.ts +++ b/src/handlers/circulatingSupply.ts @@ -15,7 +15,7 @@ async function get_circulating_supply(circulating_supply_watchlist: string[]): P let non_circulating_accounts = await bd_api.get_accounts(filtered_accounts.other); - let non_circulating_accounts_delayed = await Promise.all(filtered_accounts?.delayed?.map(address => node_api.auth_get_account(address))); + let non_circulating_accounts_delayed = await Promise.all(filtered_accounts?.delayed?.map(address => node_api.bank_get_account_balances(address))); // Calculate total balance of watchlist accounts let non_circulating_supply_ncheq = non_circulating_accounts.map(total_balance_ncheq).reduce((a, b) => a + b, 0); diff --git a/src/helpers/node.ts b/src/helpers/node.ts index 60560378..067a3462 100644 --- a/src/helpers/node.ts +++ b/src/helpers/node.ts @@ -1,5 +1,5 @@ import { Account } from "../types/bigDipper"; -import { Account as AccountCosmos } from "../types/node"; +import { Coin } from "../types/node"; export function total_balance_ncheq(account: Account): number { let balance = Number(account?.accountBalances[0]?.coins.find(c => c.denom === "ncheq")?.amount || '0'); @@ -23,6 +23,6 @@ export function total_balance_ncheq(account: Account): number { return balance + delegations + unbonding + rewards; } -export function delayed_balance_ncheq(account: AccountCosmos): number { - return Number(account?.base_vesting_account.original_vesting.find(c => c.denom === "ncheq")?.amount || '0'); +export function delayed_balance_ncheq(balance: Coin[]): number { + return Number(balance.find(c => c.denom === "ncheq")?.amount || '0'); } From 5d7250dd707d9b76670834dad390c9b55de8c551 Mon Sep 17 00:00:00 2001 From: Ankur Banerjee Date: Fri, 3 Jun 2022 16:25:28 +0100 Subject: [PATCH 16/20] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dd811936..e5de2ef8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ ### APP-SPECIFIC EXCLUSIONS ### wrangler.dev.toml watchlist.json - +watchlist-old.json ### GENERAL EXCLUSIONS ### From d5af7b2939f2c3eb28a9fe06239b9d4692af6ca4 Mon Sep 17 00:00:00 2001 From: Ankur Banerjee Date: Fri, 3 Jun 2022 17:03:20 +0100 Subject: [PATCH 17/20] Update README with new circulating supply calculations --- README.md | 59 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index c8cd79ae..93c97394 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This collection of custom APIs can be deployed as a [Cloudflare Worker](https:// #### Endpoints -`/` or `/supply/total` (available at [data-api.cheqd.io/supply/total](https://data-api.cheqd.io/supply/total)) +[`data-api.cheqd.io/supply/total`](https://data-api.cheqd.io/supply/total) (also has an API endpoint alias on `/`) #### Response @@ -28,11 +28,11 @@ While this figure is available from Cosmos SDK's built-in [`/cosmos/bank/v1beta1 #### Endpoint -`/supply/circulating` (available at [data-api.cheqd.io/supply/circulating](https://data-api.cheqd.io/supply/circulating)) +[`data-api.cheqd.io/supply/circulating`](https://data-api.cheqd.io/supply/circulating) #### Response -Circulating token supply, in main token denomination (CHEQ instead of `ncheq` in our case) +Circulating token supply, in main token denomination (CHEQ instead of *ncheq* in our case) #### Rationale @@ -40,13 +40,18 @@ Cryptocurrency tracking websites such as [CoinMarketCap](https://coinmarketcap.c This figure is *not* available from any Cosmos SDK API, because the [criteria for determining circulating vs "non-circulating" accounts is defined by CoinMarketCap](https://support.coinmarketcap.com/hc/en-us/articles/360043396252-Supply-Circulating-Total-Max-). -This API calculates the circulating supply by **subtracting** the account balances of a defined list of wallet addresses ("circulating supply watchlist"). +This API calculates the circulating supply by **subtracting** the account balances of a defined list of wallet addresses ("circulating supply watchlist"). Different types of accounts defined in the watchlist are handled as follows: + +1. **Base accounts and Continuous Vesting accounts**: These will always have an entry in BigDipper block explorer, since these accounts have transactions that trigger indexing. +2. **Delayed Vesting accounts**: These accounts present a complex scenario since BigDipper does *not* index all delayed vesting accounts by default. + 1. **If there have been ANY transactions involving the delayed vesting account**: Delayed vesting accounts can still stake their original vesting allowance, or the account holder may have transferred additional funds into the account. In this scenario, the account *will* be indexed by BigDipper and the account balance can be fetched via the GraphQL API. + 2. **If there have been NO transactions involving the delayed vesting account**: Delayed vesting accounts with no other transactions beyond the original creation are *not* indexed by BigDipper. Balances for these accounts are fetched using the standard Cosmos SDK `/cosmos/bank/v1beta1/balances/
` REST API endpoint. ### 🔐 Vesting Account Balance #### Endpoint -`/balances/vesting/
` (e.g., [data-api.cheqd.io/balances/vesting/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg](https://data-api.cheqd.io/balances/vesting/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg)) +[`data-api.cheqd.io/balances/vesting/
`](https://data-api.cheqd.io/balances/vesting/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg) #### Response @@ -56,25 +61,43 @@ Tokens that are still vesting for continuous/delayed vesting accounts, in CHEQ. There is no Cosmos SDK API that returns balances that are yet to be vested for [continuous or delayed vesting accounts](https://docs.cosmos.network/master/modules/auth/05_vesting.html#vesting-account-types). +### 🔒 Vested Account Balance + +#### Endpoint + +[`data-api.cheqd.io/balances/vested/
`](https://data-api.cheqd.io/balances/vesting/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg) + +#### Response + +Tokens that have already vested for continuous/delayed vesting accounts, in CHEQ. + +#### Rationale + +There is no Cosmos SDK API that returns balances that are already vested for [continuous or delayed vesting accounts](https://docs.cosmos.network/master/modules/auth/05_vesting.html#vesting-account-types). + ### 💸 Liquid Account Balance #### Endpoint -`/balances/liquid/
` (e.g., [data-api.cheqd.io/balances/liquid/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg](https://data-api.cheqd.io/balances/liquid/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg)) +[`data-api.cheqd.io/balances/liquid/
`](https://data-api.cheqd.io/balances/vesting/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg) #### Response -Tokens in continuous/delayed vesting accounts that can actually be spent/transferred with no wait time, in CHEQ. +Tokens in continuous/delayed vesting accounts that can be converted to liquid balances, in CHEQ. #### Rationale -Tokens in [continuous or delayed vesting accounts](https://docs.cosmos.network/master/modules/auth/05_vesting.html#vesting-account-types) can be delegated even if they are not yet vested. This results in a scenario where an account might be able to stake a large part of their vesting balance, but the liquid amount available (e.g., to pay for transaction fees) is not easily available from Cosmos SDK's built-in REST APIs. +Tokens in [continuous or delayed vesting accounts](https://docs.cosmos.network/master/modules/auth/05_vesting.html#vesting-account-types) that can be converted to liquid balances. This is calculated as the sum of the following figures: + +1. "Delegated free" balance (from the `/cosmos/auth/v1beta1/accounts/
` REST API) *or* vested balance, whichever is higher +2. "Available" balance (if applicable) +3. "Reward" balance (if applicable) ### 💰 Total Account Balance #### Endpoint -`/balances/total/
` (e.g., [data-api.cheqd.io/balances/total/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg](https://data-api.cheqd.io/balances/total/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg)) +[`data-api.cheqd.io/balances/total/
`](https://data-api.cheqd.io/balances/total/cheqd1qs0nhyk868c246defezhz5eymlt0dmajna2csg) #### Response @@ -112,6 +135,8 @@ Wrangler CLI uses [`wrangler.toml` for configuring](https://developers.cloudflar For the circulating supply API endpoint, Cloudflare Workers will expect to find a Cloudflare KV namespace called `CIRCULATING_SUPPLY_WATCHLIST` with a list of addresses in the `key`. The application *only* uses the key, so value can be anything. +Delayed vesting accounts that have never been involved in a transaction (as described above) should be prefixed with a `delayed:` prefix in the JSON file. Cloudflare allows [filtering KV pair `key`s by prefixes](https://developers.cloudflare.com/workers/runtime-apis/kv/#more-detail) when using a list operation. + ```jsonc // Sample watchlist JSON file structure [ @@ -119,17 +144,31 @@ For the circulating supply API endpoint, Cloudflare Workers will expect to find "key": "cheqd1...xxx", "value": "26-May-2022" // This can be any value }, + { + "key": "delayed:cheqd1...xxx", // This is a delayed account that won't be indexed by BigDipper + "value": "26-May-2022" + }, ] ``` Tip: There are online converter tools to [transform CSV files to JSON files](https://csvjson.com/csv2json), which is an easy way of converting spreadsheets to JSON. -Entries can bulk-uploaded to Cloudflare KV using Wrangler CLI (see [Wrangler CLI documentation for understanding the `kv:bulk` command](https://developers.cloudflare.com/workers/wrangler/commands/#kvbulk) parameters): +#### Bulk-uploading to Cloudflare KV + +Entries can [bulk-uploaded to Cloudflare KV using Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/commands/#kvbulk): ```bash wrangler kv:bulk put --binding "CIRCULATING_SUPPLY_WATCHLIST" --preview false ``` +#### Bulk-deleting from Cloudflare KV + +Entries can [bulk-deleted from Cloudflare KV using Wrangler CLI](https://developers.cloudflare.com/workers/wrangler/commands/#kvbulk) by providing a JSON file with list of keys to delete. This JSON file should be in the form `["key1", "key2", ...]`. + +```bash +wrangler kv:bulk delete --binding "CIRCULATING_SUPPLY_WATCHLIST" --preview false +``` + ### Local Development Wrangler CLI can serve a preview where the code and KV pairs are served from Cloudflare. This also automatically executes a build to be able to serve up the app. From e286e2a312779a213387cb604bb4f7a32485dcdf Mon Sep 17 00:00:00 2001 From: Ankur Banerjee Date: Fri, 3 Jun 2022 17:09:27 +0100 Subject: [PATCH 18/20] Update package.json --- package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 21210a82..0ff1306e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,10 @@ { "name": "data-api", - "version": "0.1.0", + "version": "1.0.1", + "licence": "Apache-2.0", + "source": "src/index.ts", + "repository": "git://github.com/cheqd/data-api.git", + "author": "Cheqd Foundation Limited (https://github.com/cheqd)", "devDependencies": { "@cloudflare/workers-types": "^3.11.0", "@types/node": "^17.0.35", From 2cc5a7cdbcf20223e3b11727760e4b984893c4bf Mon Sep 17 00:00:00 2001 From: Ankur Banerjee Date: Fri, 3 Jun 2022 17:35:11 +0100 Subject: [PATCH 19/20] Delete package-lock.json --- package-lock.json | 1718 --------------------------------------------- 1 file changed, 1718 deletions(-) delete mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 9d4543e6..00000000 --- a/package-lock.json +++ /dev/null @@ -1,1718 +0,0 @@ -{ - "name": "data-api", - "version": "0.1.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "data-api", - "version": "0.1.0", - "dependencies": { - "itty-router": "^2.6.1" - }, - "devDependencies": { - "@cloudflare/workers-types": "^3.11.0", - "@types/node": "^17.0.35", - "typescript": "^4.6.4", - "wrangler": "https://prerelease-registry.developers.workers.dev/runs/2377087436/npm-package-wrangler-1097" - } - }, - "node_modules/@cloudflare/workers-types": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-3.11.0.tgz", - "integrity": "sha512-XmKgZZHrCdPsoVQkdd365R7GvwTwDVJsMyEG3Dq/Tgxz6vgrps2c8PXBqEutguwvl0zDAF0AL0e2Z8WG9Dffjw==", - "dev": true - }, - "node_modules/@esbuild-plugins/node-globals-polyfill": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.1.1.tgz", - "integrity": "sha512-MR0oAA+mlnJWrt1RQVQ+4VYuRJW/P2YmRTv1AsplObyvuBMnPHiizUF95HHYiSsMGLhyGtWufaq2XQg6+iurBg==", - "dev": true, - "peerDependencies": { - "esbuild": "*" - } - }, - "node_modules/@esbuild-plugins/node-modules-polyfill": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.1.4.tgz", - "integrity": "sha512-uZbcXi0zbmKC/050p3gJnne5Qdzw8vkXIv+c2BW0Lsc1ji1SkrxbKPUy5Efr0blbTu1SL8w4eyfpnSdPg3G0Qg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^4.0.0", - "rollup-plugin-node-polyfills": "^0.2.1" - }, - "peerDependencies": { - "esbuild": "*" - } - }, - "node_modules/@iarna/toml": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", - "dev": true - }, - "node_modules/@miniflare/cache": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.4.0.tgz", - "integrity": "sha512-tMDXlUVlThgFubJmlxZoKmLK8kBxDmuMbVMt7csHpXegzkuo2TmIsDqBE/C3CRiJ5xeCQgpD6iZtKBu5Zn5fRA==", - "dev": true, - "dependencies": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "http-cache-semantics": "^4.1.0", - "undici": "4.13.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/cli-parser": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.4.0.tgz", - "integrity": "sha512-Xr5lO8f+oIr9r/b2dfo0on1p0MNN+pkwRHWoY5ACSnp9FaGnwm/g71DM7AajIQPIk0TpRsSVNDx8Ygj1LPT+sQ==", - "dev": true, - "dependencies": { - "@miniflare/shared": "2.4.0", - "kleur": "^4.1.4" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.4.0.tgz", - "integrity": "sha512-vYl8xaWTFzxtkbzx3IkT4Py0OAFdfmFnVo627O1HKHWVGlkjVr8UKtxBpIR+f5pq/HCMzzqA1HM9FXO0dQfy3A==", - "dev": true, - "dependencies": { - "@iarna/toml": "^2.2.5", - "@miniflare/shared": "2.4.0", - "@miniflare/watcher": "2.4.0", - "busboy": "^0.3.1", - "dotenv": "^10.0.0", - "kleur": "^4.1.4", - "set-cookie-parser": "^2.4.8", - "undici": "4.13.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/durable-objects": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.4.0.tgz", - "integrity": "sha512-VVLaUXXcAQcYE/3YmDLTacZf5OzR8bib6q1T9NqVb0uK5sLMQqyHvQdsG5rMqs7iyxfJxyZ0bL2OW9XGALOkoQ==", - "dev": true, - "dependencies": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "@miniflare/storage-memory": "2.4.0", - "undici": "4.13.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/html-rewriter": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.4.0.tgz", - "integrity": "sha512-ZG8819N7LelDD+8+Ss5FZpVyQQq/V2igod0qE68JK4he/w4/yn57Rk6Efb49y15HoHAXl2RpCCsnCyIow/Xjug==", - "dev": true, - "dependencies": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "html-rewriter-wasm": "^0.4.1", - "undici": "4.13.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/http-server": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.4.0.tgz", - "integrity": "sha512-r6Z/nqxE0oa1z63L95yvnG0PUeLRxZOeGS7ADxZMFKan4WD5lvYtSKDuDEm0lkbQshCOHQ3uXFr0cotOm8JoMQ==", - "dev": true, - "dependencies": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "@miniflare/web-sockets": "2.4.0", - "kleur": "^4.1.4", - "selfsigned": "^2.0.0", - "undici": "4.13.0", - "ws": "^8.2.2", - "youch": "^2.2.2" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/kv": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.4.0.tgz", - "integrity": "sha512-1UW7f1386xR6EDEXNZOR1TpFwQfRRSxUPqD6m/U0WprlsbM0cIYGz+AUeaVbkFf8lfE2MeXCUrjbWsLOvsnw3g==", - "dev": true, - "dependencies": { - "@miniflare/shared": "2.4.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/runner-vm": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.4.0.tgz", - "integrity": "sha512-7sdwBYzXQTwYeR3tTvQ+vJfzc7BXwqR8AUPK9l5gvCtg+Geq9sMslr5SikIJpgcvbYqKDjvC9DQEPJ3sqr9cSQ==", - "dev": true, - "dependencies": { - "@miniflare/shared": "2.4.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/scheduler": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.4.0.tgz", - "integrity": "sha512-dfMCXoAS8Y+3xABNxYju62I2xIBS54Op7ohCHoatvAM5RvualJUPICEMPZzX6/z29q5xPIeSLhLDhl/asAQ19w==", - "dev": true, - "dependencies": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "cron-schedule": "^3.0.4" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/shared": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.4.0.tgz", - "integrity": "sha512-lPQFzBUVGNQ93gQ/dliToWnO0OqAgsD3/902Pd/IixVSRwRj3BTnYv2dHMUKZcODBPrhnbqZeqcPWdBLzEx8uw==", - "dev": true, - "dependencies": { - "ignore": "^5.1.8", - "kleur": "^4.1.4" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/sites": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.4.0.tgz", - "integrity": "sha512-YZy/TujnR1lkBvCncDDQ8tsWsXRE4JJ4x9a0bKN/XnZh7r6OhDM0sw4BFcBQhT6Ukdtttam1O3FlJxnMitrDGg==", - "dev": true, - "dependencies": { - "@miniflare/kv": "2.4.0", - "@miniflare/shared": "2.4.0", - "@miniflare/storage-file": "2.4.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/storage-file": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.4.0.tgz", - "integrity": "sha512-f1AUMz8xps/4VhNJMb8JeCevZFeU4pg2lIWmC11gG4xeq2nibTPBi6Qtx594Le7ZKij/tF6rRsoNfGau2Q5gdw==", - "dev": true, - "dependencies": { - "@miniflare/shared": "2.4.0", - "@miniflare/storage-memory": "2.4.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/storage-memory": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.4.0.tgz", - "integrity": "sha512-mhWwgHhDNtEa7y1bYbdVucV0lqUmzagYXUSppAdSGS5JPyJMyw3HseqRNTk6gC/vKlvEYlFf3ugWcREGCedr9A==", - "dev": true, - "dependencies": { - "@miniflare/shared": "2.4.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/watcher": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.4.0.tgz", - "integrity": "sha512-gDQRUxwOjmctvowyd4Hcdy3fjxz3ERKzirp6TvA3AWUohKZk3IhwGlaA8aCwbdP+ELYQlG5wK44AfLSGi956fg==", - "dev": true, - "dependencies": { - "@miniflare/shared": "2.4.0" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@miniflare/web-sockets": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.4.0.tgz", - "integrity": "sha512-cz/cN0GoQOXRLh80UmlcEJODPIw2ijKBK3PLRzvfTzqQ5avK6wp2M8Fj8C/5JIT6g7siwvBANyKXD3U3RpKGHQ==", - "dev": true, - "dependencies": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "undici": "4.13.0", - "ws": "^8.2.2" - }, - "engines": { - "node": ">=16.7" - } - }, - "node_modules/@types/node": { - "version": "17.0.35", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz", - "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==", - "dev": true - }, - "node_modules/@types/stack-trace": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/stack-trace/-/stack-trace-0.0.29.tgz", - "integrity": "sha512-TgfOX+mGY/NyNxJLIbDWrO9DjGoVSW9+aB8H2yy1fy32jsvxijhmyJI9fDFgvz3YP4lvJaq9DzdR/M1bOgVc9g==", - "dev": true - }, - "node_modules/blake3-wasm": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", - "dev": true - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/busboy": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", - "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", - "dev": true, - "dependencies": { - "dicer": "0.3.0" - }, - "engines": { - "node": ">=4.5.0" - } - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/cron-schedule": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.6.tgz", - "integrity": "sha512-izfGgKyzzIyLaeb1EtZ3KbglkS6AKp9cv7LxmiyoOu+fXfol1tQDC0Cof0enVZGNtudTHW+3lfuW9ZkLQss4Wg==", - "dev": true - }, - "node_modules/dicer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", - "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", - "dev": true, - "dependencies": { - "streamsearch": "0.1.2" - }, - "engines": { - "node": ">=4.5.0" - } - }, - "node_modules/dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/esbuild": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.34.tgz", - "integrity": "sha512-QIWdPT/gFF6hCaf4m7kP0cJ+JIuFkdHibI7vVFvu3eJS1HpVmYHWDulyN5WXwbRA0SX/7ZDaJ/1DH8SdY9xOJg==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "esbuild-android-64": "0.14.34", - "esbuild-android-arm64": "0.14.34", - "esbuild-darwin-64": "0.14.34", - "esbuild-darwin-arm64": "0.14.34", - "esbuild-freebsd-64": "0.14.34", - "esbuild-freebsd-arm64": "0.14.34", - "esbuild-linux-32": "0.14.34", - "esbuild-linux-64": "0.14.34", - "esbuild-linux-arm": "0.14.34", - "esbuild-linux-arm64": "0.14.34", - "esbuild-linux-mips64le": "0.14.34", - "esbuild-linux-ppc64le": "0.14.34", - "esbuild-linux-riscv64": "0.14.34", - "esbuild-linux-s390x": "0.14.34", - "esbuild-netbsd-64": "0.14.34", - "esbuild-openbsd-64": "0.14.34", - "esbuild-sunos-64": "0.14.34", - "esbuild-windows-32": "0.14.34", - "esbuild-windows-64": "0.14.34", - "esbuild-windows-arm64": "0.14.34" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.34.tgz", - "integrity": "sha512-XfxcfJqmMYsT/LXqrptzFxmaR3GWzXHDLdFNIhm6S00zPaQF1TBBWm+9t0RZ6LRR7iwH57DPjaOeW20vMqI4Yw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.34.tgz", - "integrity": "sha512-T02+NXTmSRL1Mc6puz+R9CB54rSPICkXKq6+tw8B6vxZFnCPzbJxgwIX4kcluz9p8nYBjF3+lSilTGWb7+Xgew==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.34.tgz", - "integrity": "sha512-pLRip2Bh4Ng7Bf6AMgCrSp3pPe/qZyf11h5Qo2mOfJqLWzSVjxrXW+CFRJfrOVP7TCnh/gmZSM2AFdCPB72vtw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.34.tgz", - "integrity": "sha512-vpidSJEBxx6lf1NWgXC+DCmGqesJuZ5Y8aQVVsaoO4i8tRXbXb0whChRvop/zd3nfNM4dIl5EXAky0knRX5I6w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.34.tgz", - "integrity": "sha512-m0HBjePhe0hAQJgtMRMNV9kMgIyV4/qSnzPx42kRMQBcPhgjAq1JRu4Il26czC+9FgpMbFkUktb07f/Lwnc6CA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.34.tgz", - "integrity": "sha512-cpRc2B94L1KvMPPYB4D6G39jLqpKlD3noAMY4/e86iXXXkhUYJJEtTuyNFTa9JRpWM0xCAp4mxjHjoIiLuoCLA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.34.tgz", - "integrity": "sha512-8nQaEaoW7MH/K/RlozJa+lE1ejHIr8fuPIHhc513UebRav7HtXgQvxHQ6VZRUkWtep23M6dd7UqhwO1tMOfzQQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.34.tgz", - "integrity": "sha512-Y3of4qQoLLlAgf042MlrY1P+7PnN9zWj8nVtw9XQG5hcLOZLz7IKpU35oeu7n4wvyaZHwvQqDJ93gRLqdJekcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.34.tgz", - "integrity": "sha512-9lpq1NcJqssAF7alCO6zL3gvBVVt/lKw4oetUM7OgNnRX0OWpB+ZIO9FwCrSj/dMdmgDhPLf+119zB8QxSMmAg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.34.tgz", - "integrity": "sha512-IlWaGtj9ir7+Nrume1DGcyzBDlK8GcnJq0ANKwcI9pVw8tqr+6GD0eqyF9SF1mR8UmAp+odrx1H5NdR2cHdFHA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.34.tgz", - "integrity": "sha512-k3or+01Rska1AjUyNjA4buEwB51eyN/xPQAoOx1CjzAQC3l8rpjUDw55kXyL63O/1MUi4ISvtNtl8gLwdyEcxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.34.tgz", - "integrity": "sha512-+qxb8M9FfM2CJaVU7GgYpJOHM1ngQOx+/VrtBjb4C8oVqaPcESCeg2anjl+HRZy8VpYc71q/iBYausPPbJ+Keg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.34.tgz", - "integrity": "sha512-Y717ltBdQ5j5sZIHdy1DV9kieo0wMip0dCmVSTceowCPYSn1Cg33Kd6981+F/3b9FDMzNWldZFOBRILViENZSA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.34.tgz", - "integrity": "sha512-bDDgYO4LhL4+zPs+WcBkXph+AQoPcQRTv18FzZS0WhjfH8TZx2QqlVPGhmhZ6WidrY+jKthUqO6UhGyIb4MpmA==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.34.tgz", - "integrity": "sha512-cfaFGXdRt0+vHsjNPyF0POM4BVSHPSbhLPe8mppDc7GDDxjIl08mV1Zou14oDWMp/XZMjYN1kWYRSfftiD0vvQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.34.tgz", - "integrity": "sha512-vmy9DxXVnRiI14s8GKuYBtess+EVcDALkbpTqd5jw4XITutIzyB7n4x0Tj5utAkKsgZJB22lLWGekr0ABnSLow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.34.tgz", - "integrity": "sha512-eNPVatNET1F7tRMhii7goL/eptfxc0ALRjrj9SPFNqp0zmxrehBFD6BaP3R4LjMn6DbMO0jOAnTLFKr8NqcJAA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.34.tgz", - "integrity": "sha512-EFhpXyHEcnqWYe2rAHFd8dRw8wkrd9U+9oqcyoEL84GbanAYjiiIjBZsnR8kl0sCQ5w6bLpk7vCEIA2VS32Vcg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.34.tgz", - "integrity": "sha512-a8fbl8Ky7PxNEjf1aJmtxdDZj32/hC7S1OcA2ckEpCJRTjiKslI9vAdPpSjrKIWhws4Galpaawy0nB7fjHYf5Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.34.tgz", - "integrity": "sha512-EYvmKbSa2B3sPnpC28UEu9jBK5atGV4BaVRE7CYGUci2Hlz4AvtV/LML+TcDMT6gBgibnN2gcltWclab3UutMg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/html-rewriter-wasm": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/html-rewriter-wasm/-/html-rewriter-wasm-0.4.1.tgz", - "integrity": "sha512-lNovG8CMCCmcVB1Q7xggMSf7tqPCijZXaH4gL6iE8BFghdQCbaY5Met9i1x2Ex8m/cZHDUtXK9H6/znKamRP8Q==", - "dev": true - }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/itty-router": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/itty-router/-/itty-router-2.6.1.tgz", - "integrity": "sha512-l9gxWe5TOLUESYnBn85Jxd6tIZLWdRX5YKkHIBfSgbNQ7UFPNUGuWihRV+LlEbfJJIzgLmhwAbaWRi5yWJm8kg==" - }, - "node_modules/kleur": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", - "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "dependencies": { - "sourcemap-codec": "^1.4.8" - } - }, - "node_modules/miniflare": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.4.0.tgz", - "integrity": "sha512-xOBL/dQsUL95rxIYO+KrrVPPpm2TAf6TKl4AvhcjSfUeVkzDWd/y9f7hXCt8x6srDoK0Z2LpYouatvSfSUzGOw==", - "dev": true, - "dependencies": { - "@miniflare/cache": "2.4.0", - "@miniflare/cli-parser": "2.4.0", - "@miniflare/core": "2.4.0", - "@miniflare/durable-objects": "2.4.0", - "@miniflare/html-rewriter": "2.4.0", - "@miniflare/http-server": "2.4.0", - "@miniflare/kv": "2.4.0", - "@miniflare/runner-vm": "2.4.0", - "@miniflare/scheduler": "2.4.0", - "@miniflare/shared": "2.4.0", - "@miniflare/sites": "2.4.0", - "@miniflare/storage-file": "2.4.0", - "@miniflare/storage-memory": "2.4.0", - "@miniflare/web-sockets": "2.4.0", - "kleur": "^4.1.4", - "semiver": "^1.1.0", - "source-map-support": "^0.5.20", - "undici": "4.13.0" - }, - "bin": { - "miniflare": "bootstrap.js" - }, - "engines": { - "node": ">=16.7" - }, - "peerDependencies": { - "@miniflare/storage-redis": "2.4.0", - "cron-schedule": "^3.0.4", - "ioredis": "^4.27.9" - }, - "peerDependenciesMeta": { - "@miniflare/storage-redis": { - "optional": true - }, - "cron-schedule": { - "optional": true - }, - "ioredis": { - "optional": true - } - } - }, - "node_modules/mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "dev": true, - "bin": { - "mustache": "bin/mustache" - } - }, - "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true, - "engines": { - "node": ">= 6.13.0" - } - }, - "node_modules/path-to-regexp": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", - "dev": true - }, - "node_modules/rollup-plugin-inject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", - "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", - "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-inject.", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1", - "magic-string": "^0.25.3", - "rollup-pluginutils": "^2.8.1" - } - }, - "node_modules/rollup-plugin-node-polyfills": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", - "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", - "dev": true, - "dependencies": { - "rollup-plugin-inject": "^3.0.0" - } - }, - "node_modules/rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "dependencies": { - "estree-walker": "^0.6.1" - } - }, - "node_modules/selfsigned": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz", - "integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==", - "dev": true, - "dependencies": { - "node-forge": "^1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semiver": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", - "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/set-cookie-parser": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", - "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==", - "dev": true - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "node_modules/stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/typescript": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz", - "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/undici": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-4.13.0.tgz", - "integrity": "sha512-8lk8S/f2V0VUNGf2scU2b+KI2JSzEQLdCyRNRF3XmHu+5jectlSDaPSBCXAHFaUlt1rzngzOBVDgJS9/Gue/KA==", - "dev": true, - "engines": { - "node": ">=12.18" - } - }, - "node_modules/wrangler": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.0.6.tgz", - "integrity": "sha512-LO3iTWZCPY5cWg5Ocx0j3awchBAfJtHTa21MFv0/m/AJC5FdATvH/agZ100dkOaF3/qmQVFsMI3EDx9/PiRjmg==", - "dev": true, - "dependencies": { - "@esbuild-plugins/node-globals-polyfill": "^0.1.1", - "@esbuild-plugins/node-modules-polyfill": "^0.1.4", - "blake3-wasm": "^2.1.5", - "esbuild": "0.14.34", - "miniflare": "2.4.0", - "nanoid": "^3.3.3", - "path-to-regexp": "^6.2.0", - "selfsigned": "^2.0.1", - "semiver": "^1.1.0", - "xxhash-wasm": "^1.0.1" - }, - "bin": { - "wrangler": "bin/wrangler.js", - "wrangler2": "bin/wrangler.js" - }, - "engines": { - "node": ">=16.7.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/ws": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", - "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xxhash-wasm": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.1.tgz", - "integrity": "sha512-Lc9CTvDrH2vRoiaUzz25q7lRaviMhz90pkx6YxR9EPYtF99yOJnv2cB+CQ0hp/TLoqrUsk8z/W2EN31T568Azw==", - "dev": true - }, - "node_modules/youch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/youch/-/youch-2.2.2.tgz", - "integrity": "sha512-/FaCeG3GkuJwaMR34GHVg0l8jCbafZLHiFowSjqLlqhC6OMyf2tPJBu8UirF7/NI9X/R5ai4QfEKUCOxMAGxZQ==", - "dev": true, - "dependencies": { - "@types/stack-trace": "0.0.29", - "cookie": "^0.4.1", - "mustache": "^4.2.0", - "stack-trace": "0.0.10" - } - } - }, - "dependencies": { - "@cloudflare/workers-types": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-3.11.0.tgz", - "integrity": "sha512-XmKgZZHrCdPsoVQkdd365R7GvwTwDVJsMyEG3Dq/Tgxz6vgrps2c8PXBqEutguwvl0zDAF0AL0e2Z8WG9Dffjw==", - "dev": true - }, - "@esbuild-plugins/node-globals-polyfill": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.1.1.tgz", - "integrity": "sha512-MR0oAA+mlnJWrt1RQVQ+4VYuRJW/P2YmRTv1AsplObyvuBMnPHiizUF95HHYiSsMGLhyGtWufaq2XQg6+iurBg==", - "dev": true, - "requires": {} - }, - "@esbuild-plugins/node-modules-polyfill": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-modules-polyfill/-/node-modules-polyfill-0.1.4.tgz", - "integrity": "sha512-uZbcXi0zbmKC/050p3gJnne5Qdzw8vkXIv+c2BW0Lsc1ji1SkrxbKPUy5Efr0blbTu1SL8w4eyfpnSdPg3G0Qg==", - "dev": true, - "requires": { - "escape-string-regexp": "^4.0.0", - "rollup-plugin-node-polyfills": "^0.2.1" - } - }, - "@iarna/toml": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-2.2.5.tgz", - "integrity": "sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==", - "dev": true - }, - "@miniflare/cache": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/cache/-/cache-2.4.0.tgz", - "integrity": "sha512-tMDXlUVlThgFubJmlxZoKmLK8kBxDmuMbVMt7csHpXegzkuo2TmIsDqBE/C3CRiJ5xeCQgpD6iZtKBu5Zn5fRA==", - "dev": true, - "requires": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "http-cache-semantics": "^4.1.0", - "undici": "4.13.0" - } - }, - "@miniflare/cli-parser": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/cli-parser/-/cli-parser-2.4.0.tgz", - "integrity": "sha512-Xr5lO8f+oIr9r/b2dfo0on1p0MNN+pkwRHWoY5ACSnp9FaGnwm/g71DM7AajIQPIk0TpRsSVNDx8Ygj1LPT+sQ==", - "dev": true, - "requires": { - "@miniflare/shared": "2.4.0", - "kleur": "^4.1.4" - } - }, - "@miniflare/core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/core/-/core-2.4.0.tgz", - "integrity": "sha512-vYl8xaWTFzxtkbzx3IkT4Py0OAFdfmFnVo627O1HKHWVGlkjVr8UKtxBpIR+f5pq/HCMzzqA1HM9FXO0dQfy3A==", - "dev": true, - "requires": { - "@iarna/toml": "^2.2.5", - "@miniflare/shared": "2.4.0", - "@miniflare/watcher": "2.4.0", - "busboy": "^0.3.1", - "dotenv": "^10.0.0", - "kleur": "^4.1.4", - "set-cookie-parser": "^2.4.8", - "undici": "4.13.0" - } - }, - "@miniflare/durable-objects": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/durable-objects/-/durable-objects-2.4.0.tgz", - "integrity": "sha512-VVLaUXXcAQcYE/3YmDLTacZf5OzR8bib6q1T9NqVb0uK5sLMQqyHvQdsG5rMqs7iyxfJxyZ0bL2OW9XGALOkoQ==", - "dev": true, - "requires": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "@miniflare/storage-memory": "2.4.0", - "undici": "4.13.0" - } - }, - "@miniflare/html-rewriter": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/html-rewriter/-/html-rewriter-2.4.0.tgz", - "integrity": "sha512-ZG8819N7LelDD+8+Ss5FZpVyQQq/V2igod0qE68JK4he/w4/yn57Rk6Efb49y15HoHAXl2RpCCsnCyIow/Xjug==", - "dev": true, - "requires": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "html-rewriter-wasm": "^0.4.1", - "undici": "4.13.0" - } - }, - "@miniflare/http-server": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/http-server/-/http-server-2.4.0.tgz", - "integrity": "sha512-r6Z/nqxE0oa1z63L95yvnG0PUeLRxZOeGS7ADxZMFKan4WD5lvYtSKDuDEm0lkbQshCOHQ3uXFr0cotOm8JoMQ==", - "dev": true, - "requires": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "@miniflare/web-sockets": "2.4.0", - "kleur": "^4.1.4", - "selfsigned": "^2.0.0", - "undici": "4.13.0", - "ws": "^8.2.2", - "youch": "^2.2.2" - } - }, - "@miniflare/kv": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/kv/-/kv-2.4.0.tgz", - "integrity": "sha512-1UW7f1386xR6EDEXNZOR1TpFwQfRRSxUPqD6m/U0WprlsbM0cIYGz+AUeaVbkFf8lfE2MeXCUrjbWsLOvsnw3g==", - "dev": true, - "requires": { - "@miniflare/shared": "2.4.0" - } - }, - "@miniflare/runner-vm": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/runner-vm/-/runner-vm-2.4.0.tgz", - "integrity": "sha512-7sdwBYzXQTwYeR3tTvQ+vJfzc7BXwqR8AUPK9l5gvCtg+Geq9sMslr5SikIJpgcvbYqKDjvC9DQEPJ3sqr9cSQ==", - "dev": true, - "requires": { - "@miniflare/shared": "2.4.0" - } - }, - "@miniflare/scheduler": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/scheduler/-/scheduler-2.4.0.tgz", - "integrity": "sha512-dfMCXoAS8Y+3xABNxYju62I2xIBS54Op7ohCHoatvAM5RvualJUPICEMPZzX6/z29q5xPIeSLhLDhl/asAQ19w==", - "dev": true, - "requires": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "cron-schedule": "^3.0.4" - } - }, - "@miniflare/shared": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/shared/-/shared-2.4.0.tgz", - "integrity": "sha512-lPQFzBUVGNQ93gQ/dliToWnO0OqAgsD3/902Pd/IixVSRwRj3BTnYv2dHMUKZcODBPrhnbqZeqcPWdBLzEx8uw==", - "dev": true, - "requires": { - "ignore": "^5.1.8", - "kleur": "^4.1.4" - } - }, - "@miniflare/sites": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/sites/-/sites-2.4.0.tgz", - "integrity": "sha512-YZy/TujnR1lkBvCncDDQ8tsWsXRE4JJ4x9a0bKN/XnZh7r6OhDM0sw4BFcBQhT6Ukdtttam1O3FlJxnMitrDGg==", - "dev": true, - "requires": { - "@miniflare/kv": "2.4.0", - "@miniflare/shared": "2.4.0", - "@miniflare/storage-file": "2.4.0" - } - }, - "@miniflare/storage-file": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/storage-file/-/storage-file-2.4.0.tgz", - "integrity": "sha512-f1AUMz8xps/4VhNJMb8JeCevZFeU4pg2lIWmC11gG4xeq2nibTPBi6Qtx594Le7ZKij/tF6rRsoNfGau2Q5gdw==", - "dev": true, - "requires": { - "@miniflare/shared": "2.4.0", - "@miniflare/storage-memory": "2.4.0" - } - }, - "@miniflare/storage-memory": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/storage-memory/-/storage-memory-2.4.0.tgz", - "integrity": "sha512-mhWwgHhDNtEa7y1bYbdVucV0lqUmzagYXUSppAdSGS5JPyJMyw3HseqRNTk6gC/vKlvEYlFf3ugWcREGCedr9A==", - "dev": true, - "requires": { - "@miniflare/shared": "2.4.0" - } - }, - "@miniflare/watcher": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/watcher/-/watcher-2.4.0.tgz", - "integrity": "sha512-gDQRUxwOjmctvowyd4Hcdy3fjxz3ERKzirp6TvA3AWUohKZk3IhwGlaA8aCwbdP+ELYQlG5wK44AfLSGi956fg==", - "dev": true, - "requires": { - "@miniflare/shared": "2.4.0" - } - }, - "@miniflare/web-sockets": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@miniflare/web-sockets/-/web-sockets-2.4.0.tgz", - "integrity": "sha512-cz/cN0GoQOXRLh80UmlcEJODPIw2ijKBK3PLRzvfTzqQ5avK6wp2M8Fj8C/5JIT6g7siwvBANyKXD3U3RpKGHQ==", - "dev": true, - "requires": { - "@miniflare/core": "2.4.0", - "@miniflare/shared": "2.4.0", - "undici": "4.13.0", - "ws": "^8.2.2" - } - }, - "@types/node": { - "version": "17.0.35", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.35.tgz", - "integrity": "sha512-vu1SrqBjbbZ3J6vwY17jBs8Sr/BKA+/a/WtjRG+whKg1iuLFOosq872EXS0eXWILdO36DHQQeku/ZcL6hz2fpg==", - "dev": true - }, - "@types/stack-trace": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/stack-trace/-/stack-trace-0.0.29.tgz", - "integrity": "sha512-TgfOX+mGY/NyNxJLIbDWrO9DjGoVSW9+aB8H2yy1fy32jsvxijhmyJI9fDFgvz3YP4lvJaq9DzdR/M1bOgVc9g==", - "dev": true - }, - "blake3-wasm": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/blake3-wasm/-/blake3-wasm-2.1.5.tgz", - "integrity": "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g==", - "dev": true - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "busboy": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.3.1.tgz", - "integrity": "sha512-y7tTxhGKXcyBxRKAni+awqx8uqaJKrSFSNFSeRG5CsWNdmy2BIK+6VGWEW7TZnIO/533mtMEA4rOevQV815YJw==", - "dev": true, - "requires": { - "dicer": "0.3.0" - } - }, - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true - }, - "cron-schedule": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/cron-schedule/-/cron-schedule-3.0.6.tgz", - "integrity": "sha512-izfGgKyzzIyLaeb1EtZ3KbglkS6AKp9cv7LxmiyoOu+fXfol1tQDC0Cof0enVZGNtudTHW+3lfuW9ZkLQss4Wg==", - "dev": true - }, - "dicer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.3.0.tgz", - "integrity": "sha512-MdceRRWqltEG2dZqO769g27N/3PXfcKl04VhYnBlo2YhH7zPi88VebsjTKclaOyiuMaGU72hTfw3VkUitGcVCA==", - "dev": true, - "requires": { - "streamsearch": "0.1.2" - } - }, - "dotenv": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", - "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==", - "dev": true - }, - "esbuild": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.34.tgz", - "integrity": "sha512-QIWdPT/gFF6hCaf4m7kP0cJ+JIuFkdHibI7vVFvu3eJS1HpVmYHWDulyN5WXwbRA0SX/7ZDaJ/1DH8SdY9xOJg==", - "dev": true, - "requires": { - "esbuild-android-64": "0.14.34", - "esbuild-android-arm64": "0.14.34", - "esbuild-darwin-64": "0.14.34", - "esbuild-darwin-arm64": "0.14.34", - "esbuild-freebsd-64": "0.14.34", - "esbuild-freebsd-arm64": "0.14.34", - "esbuild-linux-32": "0.14.34", - "esbuild-linux-64": "0.14.34", - "esbuild-linux-arm": "0.14.34", - "esbuild-linux-arm64": "0.14.34", - "esbuild-linux-mips64le": "0.14.34", - "esbuild-linux-ppc64le": "0.14.34", - "esbuild-linux-riscv64": "0.14.34", - "esbuild-linux-s390x": "0.14.34", - "esbuild-netbsd-64": "0.14.34", - "esbuild-openbsd-64": "0.14.34", - "esbuild-sunos-64": "0.14.34", - "esbuild-windows-32": "0.14.34", - "esbuild-windows-64": "0.14.34", - "esbuild-windows-arm64": "0.14.34" - } - }, - "esbuild-android-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.34.tgz", - "integrity": "sha512-XfxcfJqmMYsT/LXqrptzFxmaR3GWzXHDLdFNIhm6S00zPaQF1TBBWm+9t0RZ6LRR7iwH57DPjaOeW20vMqI4Yw==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.34.tgz", - "integrity": "sha512-T02+NXTmSRL1Mc6puz+R9CB54rSPICkXKq6+tw8B6vxZFnCPzbJxgwIX4kcluz9p8nYBjF3+lSilTGWb7+Xgew==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.34.tgz", - "integrity": "sha512-pLRip2Bh4Ng7Bf6AMgCrSp3pPe/qZyf11h5Qo2mOfJqLWzSVjxrXW+CFRJfrOVP7TCnh/gmZSM2AFdCPB72vtw==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.34.tgz", - "integrity": "sha512-vpidSJEBxx6lf1NWgXC+DCmGqesJuZ5Y8aQVVsaoO4i8tRXbXb0whChRvop/zd3nfNM4dIl5EXAky0knRX5I6w==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.34.tgz", - "integrity": "sha512-m0HBjePhe0hAQJgtMRMNV9kMgIyV4/qSnzPx42kRMQBcPhgjAq1JRu4Il26czC+9FgpMbFkUktb07f/Lwnc6CA==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.34.tgz", - "integrity": "sha512-cpRc2B94L1KvMPPYB4D6G39jLqpKlD3noAMY4/e86iXXXkhUYJJEtTuyNFTa9JRpWM0xCAp4mxjHjoIiLuoCLA==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.34.tgz", - "integrity": "sha512-8nQaEaoW7MH/K/RlozJa+lE1ejHIr8fuPIHhc513UebRav7HtXgQvxHQ6VZRUkWtep23M6dd7UqhwO1tMOfzQQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.34.tgz", - "integrity": "sha512-Y3of4qQoLLlAgf042MlrY1P+7PnN9zWj8nVtw9XQG5hcLOZLz7IKpU35oeu7n4wvyaZHwvQqDJ93gRLqdJekcQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.34.tgz", - "integrity": "sha512-9lpq1NcJqssAF7alCO6zL3gvBVVt/lKw4oetUM7OgNnRX0OWpB+ZIO9FwCrSj/dMdmgDhPLf+119zB8QxSMmAg==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.34.tgz", - "integrity": "sha512-IlWaGtj9ir7+Nrume1DGcyzBDlK8GcnJq0ANKwcI9pVw8tqr+6GD0eqyF9SF1mR8UmAp+odrx1H5NdR2cHdFHA==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.34.tgz", - "integrity": "sha512-k3or+01Rska1AjUyNjA4buEwB51eyN/xPQAoOx1CjzAQC3l8rpjUDw55kXyL63O/1MUi4ISvtNtl8gLwdyEcxw==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.34.tgz", - "integrity": "sha512-+qxb8M9FfM2CJaVU7GgYpJOHM1ngQOx+/VrtBjb4C8oVqaPcESCeg2anjl+HRZy8VpYc71q/iBYausPPbJ+Keg==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.34.tgz", - "integrity": "sha512-Y717ltBdQ5j5sZIHdy1DV9kieo0wMip0dCmVSTceowCPYSn1Cg33Kd6981+F/3b9FDMzNWldZFOBRILViENZSA==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.34.tgz", - "integrity": "sha512-bDDgYO4LhL4+zPs+WcBkXph+AQoPcQRTv18FzZS0WhjfH8TZx2QqlVPGhmhZ6WidrY+jKthUqO6UhGyIb4MpmA==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.34.tgz", - "integrity": "sha512-cfaFGXdRt0+vHsjNPyF0POM4BVSHPSbhLPe8mppDc7GDDxjIl08mV1Zou14oDWMp/XZMjYN1kWYRSfftiD0vvQ==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.34.tgz", - "integrity": "sha512-vmy9DxXVnRiI14s8GKuYBtess+EVcDALkbpTqd5jw4XITutIzyB7n4x0Tj5utAkKsgZJB22lLWGekr0ABnSLow==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.34.tgz", - "integrity": "sha512-eNPVatNET1F7tRMhii7goL/eptfxc0ALRjrj9SPFNqp0zmxrehBFD6BaP3R4LjMn6DbMO0jOAnTLFKr8NqcJAA==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.34.tgz", - "integrity": "sha512-EFhpXyHEcnqWYe2rAHFd8dRw8wkrd9U+9oqcyoEL84GbanAYjiiIjBZsnR8kl0sCQ5w6bLpk7vCEIA2VS32Vcg==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.34.tgz", - "integrity": "sha512-a8fbl8Ky7PxNEjf1aJmtxdDZj32/hC7S1OcA2ckEpCJRTjiKslI9vAdPpSjrKIWhws4Galpaawy0nB7fjHYf5Q==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.14.34", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.34.tgz", - "integrity": "sha512-EYvmKbSa2B3sPnpC28UEu9jBK5atGV4BaVRE7CYGUci2Hlz4AvtV/LML+TcDMT6gBgibnN2gcltWclab3UutMg==", - "dev": true, - "optional": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "html-rewriter-wasm": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/html-rewriter-wasm/-/html-rewriter-wasm-0.4.1.tgz", - "integrity": "sha512-lNovG8CMCCmcVB1Q7xggMSf7tqPCijZXaH4gL6iE8BFghdQCbaY5Met9i1x2Ex8m/cZHDUtXK9H6/znKamRP8Q==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "itty-router": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/itty-router/-/itty-router-2.6.1.tgz", - "integrity": "sha512-l9gxWe5TOLUESYnBn85Jxd6tIZLWdRX5YKkHIBfSgbNQ7UFPNUGuWihRV+LlEbfJJIzgLmhwAbaWRi5yWJm8kg==" - }, - "kleur": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.4.tgz", - "integrity": "sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==", - "dev": true - }, - "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.8" - } - }, - "miniflare": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-2.4.0.tgz", - "integrity": "sha512-xOBL/dQsUL95rxIYO+KrrVPPpm2TAf6TKl4AvhcjSfUeVkzDWd/y9f7hXCt8x6srDoK0Z2LpYouatvSfSUzGOw==", - "dev": true, - "requires": { - "@miniflare/cache": "2.4.0", - "@miniflare/cli-parser": "2.4.0", - "@miniflare/core": "2.4.0", - "@miniflare/durable-objects": "2.4.0", - "@miniflare/html-rewriter": "2.4.0", - "@miniflare/http-server": "2.4.0", - "@miniflare/kv": "2.4.0", - "@miniflare/runner-vm": "2.4.0", - "@miniflare/scheduler": "2.4.0", - "@miniflare/shared": "2.4.0", - "@miniflare/sites": "2.4.0", - "@miniflare/storage-file": "2.4.0", - "@miniflare/storage-memory": "2.4.0", - "@miniflare/web-sockets": "2.4.0", - "kleur": "^4.1.4", - "semiver": "^1.1.0", - "source-map-support": "^0.5.20", - "undici": "4.13.0" - } - }, - "mustache": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", - "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", - "dev": true - }, - "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true - }, - "node-forge": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", - "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", - "dev": true - }, - "path-to-regexp": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", - "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==", - "dev": true - }, - "rollup-plugin-inject": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz", - "integrity": "sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1", - "magic-string": "^0.25.3", - "rollup-pluginutils": "^2.8.1" - } - }, - "rollup-plugin-node-polyfills": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz", - "integrity": "sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==", - "dev": true, - "requires": { - "rollup-plugin-inject": "^3.0.0" - } - }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1" - } - }, - "selfsigned": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.0.1.tgz", - "integrity": "sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==", - "dev": true, - "requires": { - "node-forge": "^1" - } - }, - "semiver": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", - "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==", - "dev": true - }, - "set-cookie-parser": { - "version": "2.4.8", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz", - "integrity": "sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", - "dev": true - }, - "typescript": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz", - "integrity": "sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==", - "dev": true - }, - "undici": { - "version": "4.13.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-4.13.0.tgz", - "integrity": "sha512-8lk8S/f2V0VUNGf2scU2b+KI2JSzEQLdCyRNRF3XmHu+5jectlSDaPSBCXAHFaUlt1rzngzOBVDgJS9/Gue/KA==", - "dev": true - }, - "wrangler": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-2.0.6.tgz", - "integrity": "sha512-LO3iTWZCPY5cWg5Ocx0j3awchBAfJtHTa21MFv0/m/AJC5FdATvH/agZ100dkOaF3/qmQVFsMI3EDx9/PiRjmg==", - "dev": true, - "requires": { - "@esbuild-plugins/node-globals-polyfill": "^0.1.1", - "@esbuild-plugins/node-modules-polyfill": "^0.1.4", - "blake3-wasm": "^2.1.5", - "esbuild": "0.14.34", - "fsevents": "~2.3.2", - "miniflare": "2.4.0", - "nanoid": "^3.3.3", - "path-to-regexp": "^6.2.0", - "selfsigned": "^2.0.1", - "semiver": "^1.1.0", - "xxhash-wasm": "^1.0.1" - } - }, - "ws": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.6.0.tgz", - "integrity": "sha512-AzmM3aH3gk0aX7/rZLYvjdvZooofDu3fFOzGqcSnQ1tOcTWwhM/o+q++E8mAyVVIyUdajrkzWUGftaVSDLn1bw==", - "dev": true, - "requires": {} - }, - "xxhash-wasm": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.0.1.tgz", - "integrity": "sha512-Lc9CTvDrH2vRoiaUzz25q7lRaviMhz90pkx6YxR9EPYtF99yOJnv2cB+CQ0hp/TLoqrUsk8z/W2EN31T568Azw==", - "dev": true - }, - "youch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/youch/-/youch-2.2.2.tgz", - "integrity": "sha512-/FaCeG3GkuJwaMR34GHVg0l8jCbafZLHiFowSjqLlqhC6OMyf2tPJBu8UirF7/NI9X/R5ai4QfEKUCOxMAGxZQ==", - "dev": true, - "requires": { - "@types/stack-trace": "0.0.29", - "cookie": "^0.4.1", - "mustache": "^4.2.0", - "stack-trace": "0.0.10" - } - } - } -} From 75ebde1cf62d68ef458287c1a261ea2e2d91c5ce Mon Sep 17 00:00:00 2001 From: Ankur Banerjee Date: Fri, 3 Jun 2022 17:47:02 +0100 Subject: [PATCH 20/20] Update vesting.ts --- src/helpers/vesting.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/helpers/vesting.ts b/src/helpers/vesting.ts index b50e3b15..f9c382c0 100644 --- a/src/helpers/vesting.ts +++ b/src/helpers/vesting.ts @@ -11,10 +11,10 @@ export function calculate_vested_coins(account: Account): number { const end_time = new Date(account.base_vesting_account.end_time * 1000).getTime(); const now = new Date().getTime(); - const time_elapsed_in_days = Math.abs(now - start_time) / 1000; - const time_vested_in_days = Math.abs(end_time - start_time) / 1000; + const time_elapsed = Math.abs(now - start_time) / 1000; + const time_vested = Math.abs(end_time - start_time) / 1000; - const ratio = Number(time_elapsed_in_days / time_vested_in_days); + const ratio = Number(time_elapsed / time_vested); return ratio * Number(account.base_vesting_account.original_vesting[0].amount); }