diff --git a/README.md b/README.md index ea3cfde22..86556b74f 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ If you want to get a cosmjs stargate or cosmwasm signer, [here are docs for our | [@cosmos-kit/keplr-mobile/](packages/keplr-mobile/) | WalletConnect | Keplr Mobile Wallet integration. | | [@cosmos-kit/leap](packages/leap) | Root Wallet | Leap Wallet integration. Use this if you want to integrate the extension, no mobile wallet connect support yet. | | [@cosmos-kit/omni](packages/omni) | Root Wallet | Omni Wallet integration. Use this if you want to integrate the extension, no mobile wallet connect support yet. | +| [@cosmos-kit/terra-extension](packages/terra-extension) | Root Wallet | Terra Station Wallet integration. Use this if you want to integrate the extension, no mobile wallet connect support yet. | | [@cosmos-kit/trust](packages/trust) | Root Wallet | Trust Wallet integration. Use this if you want to integrate the extension, no mobile wallet connect support yet. | | [@cosmos-kit/vectis](packages/vectis) | Root Wallet | Vectis Wallet integration. Use this if you want to integrate the extension, no mobile wallet connect support yet. | | [@cosmos-kit/xdefi-extension](packages/xdefi-extension) | Root Wallet | XDEFI Wallet (Extension) integration. Use this if you want to integrate the extension, no mobile wallet connect support yet. | diff --git a/packages/example/config/terra2testnet.ts b/packages/example/config/terra2testnet.ts new file mode 100644 index 000000000..2b6120b8d --- /dev/null +++ b/packages/example/config/terra2testnet.ts @@ -0,0 +1,92 @@ +/** + * remark: This is an example config file for a terra testnet chain and it should be deleted before merging. + */ +import type { Chain, AssetList } from "@chain-registry/types"; + +export const terra2testnet: Chain = { + $schema: "../../chain.schema.json", + chain_name: "terra2testnet", + status: "live", + network_type: "testnet", + pretty_name: "Terra Testnet", + chain_id: "pisco-1", + bech32_prefix: "terra", + daemon_name: "terrad", + node_home: "$HOME/.terrad", + slip44: 330, + fees: { + fee_tokens: [ + { + denom: "uluna", + fixed_min_gas_price: 0, + low_gas_price: 0.15, + average_gas_price: 0.15, + high_gas_price: 0.15, + }, + ], + }, + staking: { + staking_tokens: [ + { + denom: "uluna", + }, + ], + }, + codebase: { + git_repo: "https://github.com/terra-money/core", + recommended_version: "v2.2.0", + compatible_versions: ["v2.2.0"], + cosmos_sdk_version: "0.45.10", + tendermint_version: "0.34.22", + cosmwasm_version: "0.27", + cosmwasm_enabled: true, + }, + apis: { + rpc: [ + { + address: "https://terra-testnet-rpc.polkachu.com/", + }, + ], + rest: [ + { + address: "https://pisco-lcd.terra.dev/", + }, + ], + grpc: [], + }, + logo_URIs: { + png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/luna.png", + }, + keywords: ["testnet"], +}; + +export const terra2testnetAssets: AssetList = { + $schema: "../../assetlist.schema.json", + chain_name: "terra2testnet", + assets: [ + { + description: "The native token of Terra", + denom_units: [ + { + denom: "uluna", + exponent: 0, + aliases: [], + }, + { + denom: "luna", + exponent: 6, + aliases: [], + }, + ], + base: "uluna", + name: "Luna", + display: "luna", + symbol: "LUNA", + logo_URIs: { + png: "https://raw.githubusercontent.com/cosmos/chain-registry/master/terra2/images/luna.png", + }, + coingecko_id: "terra", + keywords: ["staking"], + }, + ], +}; diff --git a/packages/example/package.json b/packages/example/package.json index c667d30cf..7e8483075 100644 --- a/packages/example/package.json +++ b/packages/example/package.json @@ -22,7 +22,8 @@ "@cosmos-kit/keplr": "^0.33.22", "@cosmos-kit/leap": "^0.14.19", "@cosmos-kit/react": "^1.3.18", - "@cosmos-kit/terrastation": "^0.1.7", + "@cosmos-kit/terrastation": "^0.1.6", + "@cosmos-kit/terra-extension": "^0.0.1", "@cosmos-kit/vectis": "^0.15.19", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", diff --git a/packages/example/pages/_app.tsx b/packages/example/pages/_app.tsx index 10e4a9af6..0e8344f2d 100644 --- a/packages/example/pages/_app.tsx +++ b/packages/example/pages/_app.tsx @@ -13,19 +13,21 @@ import { wallets as trustWallets } from "@cosmos-kit/trust"; import { wallets as vectisWallets } from "@cosmos-kit/vectis"; import { wallets as frontierWallets } from "@cosmos-kit/frontier"; import { wallets as terrastationWallets } from "@cosmos-kit/terrastation"; +import { wallets as terraExtensionWallets } from "@cosmos-kit/terra-extension"; import { wallets as web3authWallets } from "@cosmos-kit/web3auth"; import { ChainProvider, defaultTheme } from "@cosmos-kit/react"; import { assets, chains } from "chain-registry"; import type { AppProps } from "next/app"; import { ThemeProvider } from "@cosmology-ui/react"; +import { terra2testnet, terra2testnetAssets } from "../config/terra2testnet"; function MyApp({ Component, pageProps }: AppProps) { return ( diff --git a/wallets/terra-extension/.babelrc.js b/wallets/terra-extension/.babelrc.js new file mode 100644 index 000000000..c008e9212 --- /dev/null +++ b/wallets/terra-extension/.babelrc.js @@ -0,0 +1,16 @@ +const useESModules = !!process.env.MODULE; + +module.exports = (api) => { + api.cache(() => process.env.MODULE); + return { + plugins: [ + ['@babel/transform-runtime', { useESModules }], + '@babel/proposal-object-rest-spread', + '@babel/proposal-class-properties', + '@babel/proposal-export-default-from' + ], + presets: useESModules + ? ["@babel/typescript", "@babel/react"] + : ["@babel/typescript", "@babel/env", "@babel/react"], + }; +}; diff --git a/wallets/terra-extension/.editorconfig b/wallets/terra-extension/.editorconfig new file mode 100644 index 000000000..4a7ea3036 --- /dev/null +++ b/wallets/terra-extension/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/wallets/terra-extension/.eslintignore b/wallets/terra-extension/.eslintignore new file mode 100644 index 000000000..14cc528b1 --- /dev/null +++ b/wallets/terra-extension/.eslintignore @@ -0,0 +1,7 @@ +node_modules/ +dist/ +main/ +module/ +types/ +coverage/ +/index.ts diff --git a/wallets/terra-extension/.eslintrc.json b/wallets/terra-extension/.eslintrc.json new file mode 100644 index 000000000..0ecaa20af --- /dev/null +++ b/wallets/terra-extension/.eslintrc.json @@ -0,0 +1,82 @@ +{ + "plugins": [ + "@typescript-eslint", + "simple-import-sort", + "unused-imports" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + // configures both eslint-plugin-prettier and eslint-config-prettier + "plugin:prettier/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "module", + "project": "tsconfig.json" + }, + "env": { + "es6": true, + "browser": true, + "node": true, + "jest": true + }, + "rules": { + "simple-import-sort/imports": 2, + "simple-import-sort/exports": 2, + "prettier/prettier": 2, + "unused-imports/no-unused-imports": 2, + "no-console": 1, + "no-debugger": 2, + "no-alert": 2, + "no-await-in-loop": 0, + "no-prototype-builtins": 0, + "no-return-assign": [ + "error", + "except-parens" + ], + "no-restricted-syntax": [ + 2, + "ForInStatement", + "LabeledStatement", + "WithStatement" + ], + "no-unused-vars": 0, + "@typescript-eslint/no-unused-vars": [ + "warn", + { + "argsIgnorePattern": "React|res|next|^_" + } + ], + "prefer-const": [ + "error", + { + "destructuring": "all" + } + ], + "no-unused-expressions": [ + 2, + { + "allowTaggedTemplates": true + } + ], + "comma-dangle": 0, + "jsx-quotes": [ + 2, + "prefer-double" + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + 2, + "single", + { + "avoidEscape": true, + "allowTemplateLiterals": true + } + ] + } +} diff --git a/wallets/terra-extension/.gitignore b/wallets/terra-extension/.gitignore new file mode 100644 index 000000000..a91a2f788 --- /dev/null +++ b/wallets/terra-extension/.gitignore @@ -0,0 +1,48 @@ +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# dist +main +module + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# Editors +.idea + +# Lib +lib + +# npm package lock +package-lock.json +yarn.lock + +# others +.DS_Store diff --git a/wallets/terra-extension/.npmignore b/wallets/terra-extension/.npmignore new file mode 100644 index 000000000..19e526a9f --- /dev/null +++ b/wallets/terra-extension/.npmignore @@ -0,0 +1,32 @@ +*.log +npm-debug.log* + +# Coverage directory used by tools like istanbul +coverage +.nyc_output + +# Dependency directories +node_modules + +# npm package lock +package-lock.json +yarn.lock + +# project files +__fixtures__ +__tests__ +.babelrc +.babelrc.js +.editorconfig +.eslintignore +.eslintrc +.eslintrc.js +.gitignore +.travis.yml +.vscode +CHANGELOG.md +examples +jest.config.js +package.json +src +test diff --git a/wallets/terra-extension/.npmrc b/wallets/terra-extension/.npmrc new file mode 100644 index 000000000..5fca0d518 --- /dev/null +++ b/wallets/terra-extension/.npmrc @@ -0,0 +1 @@ +scripts-prepend-node-path=true diff --git a/wallets/terra-extension/.prettierrc.json b/wallets/terra-extension/.prettierrc.json new file mode 100644 index 000000000..e49d6527b --- /dev/null +++ b/wallets/terra-extension/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "trailingComma": "es5", + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "useTabs": false +} diff --git a/wallets/terra-extension/CHANGELOG.md b/wallets/terra-extension/CHANGELOG.md new file mode 100644 index 000000000..5fe56bf71 --- /dev/null +++ b/wallets/terra-extension/CHANGELOG.md @@ -0,0 +1,8 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.0.1 (2023-01-30) + +**Note:** First release! diff --git a/wallets/terra-extension/LICENSE b/wallets/terra-extension/LICENSE new file mode 100644 index 000000000..bfcca3529 --- /dev/null +++ b/wallets/terra-extension/LICENSE @@ -0,0 +1,32 @@ +The Clear BSD License + +Copyright (c) 2022 CosmosKit Contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted (subject to the limitations in the disclaimer +below) provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY +THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/wallets/terra-extension/README.md b/wallets/terra-extension/README.md new file mode 100644 index 000000000..fc361b01a --- /dev/null +++ b/wallets/terra-extension/README.md @@ -0,0 +1,26 @@ +# @cosmos-kit/terra-extension + +

+ +

+ +

+ + + + + +

+ +CosmosKit is a wallet adapter for developers to build apps that quickly and easily interact with Cosmos blockchains and wallets. + +@cosmos-kit/leap is the leap integration for CosmosKit. + +## Credits + +🛠 Built by Cosmology — if you like our tools, please consider delegating to [our validator ⚛️](https://cosmology.tech/validator) + +Code built with the help of these related projects: + +- [create-cosmos-app](https://github.com/cosmology-tech/create-cosmos-app) Set up a modern Cosmos app by running one command ⚛️ +- [chain-registry](https://github.com/cosmology-tech/chain-registry) an npm module for the official Cosmos chain-registry diff --git a/wallets/terra-extension/index.ts b/wallets/terra-extension/index.ts new file mode 100644 index 000000000..f9f79b4a1 --- /dev/null +++ b/wallets/terra-extension/index.ts @@ -0,0 +1,2 @@ +// not for module, but for local development.. +export * from './src'; diff --git a/wallets/terra-extension/package.json b/wallets/terra-extension/package.json new file mode 100644 index 000000000..8b2f6f800 --- /dev/null +++ b/wallets/terra-extension/package.json @@ -0,0 +1,103 @@ +{ + "name": "@cosmos-kit/terra-extension", + "version": "0.0.1", + "description": "cosmos-kit wallet connector", + "author": "kanisorn@alleslab.com", + "contributors": [ + { + "name": "kanisorn" + } + ], + "homepage": "https://github.com/cosmology-tech/cosmos-kit#readme", + "license": "SEE LICENSE IN LICENSE", + "main": "main/index.js", + "module": "module/index.js", + "typings": "types/index.d.ts", + "directories": { + "lib": "src", + "test": "__tests__" + }, + "files": [ + "types", + "main", + "module" + ], + "scripts": { + "build:main": "cross-env BABEL_ENV=production babel src --out-dir main --delete-dir-on-start --extensions \".tsx,.ts,.js\"", + "build:module": "cross-env MODULE=true babel src --out-dir module --delete-dir-on-start --extensions \".tsx,.ts,.js\"", + "build": "npm run build:module && npm run build:main", + "build:ts": "tsc --project ./tsconfig.json", + "prepare": "npm run build", + "dev": "cross-env NODE_ENV=development babel-node src/index", + "lint": "eslint --ext .tsx,.ts .", + "format": "eslint --ext .tsx,.ts --fix .", + "test": "jest", + "test:watch": "jest --watch", + "test:debug": "node --inspect node_modules/.bin/jest --runInBand" + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/cosmology-tech/cosmos-kit" + }, + "keywords": [ + "cosmos-kit", + "cosmos", + "terra", + "terra-station", + "wallet" + ], + "bugs": { + "url": "https://github.com/cosmology-tech/cosmos-kit/issues" + }, + "jest": { + "testPathIgnorePatterns": [ + "main/", + "module/", + "types/" + ] + }, + "devDependencies": { + "@babel/cli": "7.18.10", + "@babel/core": "7.19.1", + "@babel/eslint-parser": "7.19.1", + "@babel/node": "7.10.5", + "@babel/plugin-proposal-class-properties": "7.18.6", + "@babel/plugin-proposal-export-default-from": "7.18.10", + "@babel/plugin-proposal-object-rest-spread": "7.18.9", + "@babel/plugin-transform-runtime": "7.19.1", + "@babel/preset-env": "7.19.1", + "@babel/preset-typescript": "7.16.7", + "@types/jest": "29.0.3", + "@typescript-eslint/eslint-plugin": "5.38.0", + "@typescript-eslint/parser": "5.38.0", + "babel-jest": "29.0.3", + "cross-env": "7.0.2", + "eslint": "8.23.1", + "eslint-config-next": "12.3.1", + "eslint-config-prettier": "8.5.0", + "eslint-plugin-prettier": "4.0.0", + "eslint-plugin-simple-import-sort": "8.0.0", + "eslint-plugin-unused-imports": "2.0.0", + "jest": "29.0.3", + "jest-in-case": "1.0.2", + "prettier": "2.1.2", + "regenerator-runtime": "0.13.7", + "ts-jest": "29.0.1", + "typescript": "4.8.3" + }, + "dependencies": { + "@babel/runtime": "7.11.2", + "@chain-registry/types": "0.13.1", + "@cosmos-kit/core": "^1.0.4", + "@terra-money/feather.js": "^1.0.0-beta.14", + "@terra-money/wallet-types": "^3.11.2", + "react-icons": "4.4.0" + }, + "peerDependencies": { + "@cosmjs/amino": ">= 0.28", + "@cosmjs/proto-signing": ">= 0.28" + } +} diff --git a/wallets/terra-extension/src/extension/chain-wallet.ts b/wallets/terra-extension/src/extension/chain-wallet.ts new file mode 100644 index 000000000..7088d9502 --- /dev/null +++ b/wallets/terra-extension/src/extension/chain-wallet.ts @@ -0,0 +1,7 @@ +import { ChainRecord, ChainWalletBase, Wallet } from '@cosmos-kit/core'; + +export class ChainTerraExtension extends ChainWalletBase { + constructor(walletInfo: Wallet, chainInfo: ChainRecord) { + super(walletInfo, chainInfo); + } +} diff --git a/wallets/terra-extension/src/extension/client.ts b/wallets/terra-extension/src/extension/client.ts new file mode 100644 index 000000000..413d4df83 --- /dev/null +++ b/wallets/terra-extension/src/extension/client.ts @@ -0,0 +1,58 @@ +import { WalletClient, WalletAccount } from '@cosmos-kit/core'; +import { TerraExtension } from './extension'; +import { OfflineSigner } from './signer'; +import { fromBase64 } from '@cosmjs/encoding'; + +export class TerraClient implements WalletClient { + readonly client: TerraExtension; + + constructor(client: TerraExtension) { + this.client = client; + } + + async disconnect() { + this.client.disconnect(); + } + + async getSimpleAccount(chainId: string) { + const account = await this.getAccount(chainId); + return { + namespace: 'cosmos', + chainId, + address: account.address, + }; + } + + async getAccount(chainId: string): Promise { + const account = await this.client.connect(); + const infos = await this.client.info(); + const networkInfo = infos[chainId]; + + if (!networkInfo) { + return Promise.reject( + `Unsupported chainId: ${chainId}. Please swap to ${chainId} network in Station Wallet.` + ); + } + + const coinTypeByChainId = networkInfo.coinType; + const accountPubkey = account.pubkey[coinTypeByChainId]; + + if (!accountPubkey) { + return Promise.reject( + `Can't find pubkey in Station Wallet.(Coin type: ${coinTypeByChainId})` + ); + } + + return { + address: account.address, + algo: 'secp256k1', + pubkey: fromBase64(accountPubkey), + }; + } + + async getOfflineSigner(chainId: string) { + const accountInfo = await this.getAccount(chainId); + + return new OfflineSigner(this.client, accountInfo); + } +} diff --git a/wallets/terra-extension/src/extension/extension.ts b/wallets/terra-extension/src/extension/extension.ts new file mode 100644 index 000000000..a71b83bf0 --- /dev/null +++ b/wallets/terra-extension/src/extension/extension.ts @@ -0,0 +1,153 @@ +import { Extension, Tx, ExtensionOptions } from '@terra-money/feather.js'; +import { NetworkInfo, Addresses, Pubkeys, ChainId } from './types'; + +type ConnectResponse = { + address: string; + addresses: Addresses; + pubkey: Pubkeys; +}; + +type InfoResponse = Record; + +type SignResponse = { + payload: { + result: Tx.Data; + }; +}; + +function isValidResult({ error, ...payload }: any): boolean { + if (typeof payload.success !== 'boolean') { + return false; + } else if ( + typeof payload.result === 'undefined' && + typeof error === 'undefined' + ) { + return false; + } + return true; +} + +export class TerraExtension { + private extension: Extension; + identifier = 'station'; + _inTransactionProgress = false; + + // resolvers + connectResolvers = new Set<[(data: any) => void, (error: any) => void]>(); + infoResolvers = new Set<[(data: any) => void, (error: any) => void]>(); + signResolvers = new Map< + number, + [(data: any) => void, (error: any) => void] + >(); + + constructor() {} + + get isAvailable(): boolean { + return this.extension.isAvailable; + } + + async init(): Promise { + this.extension = new Extension(); + + this.onResponse(); + } + + async connect() { + return new Promise((...resolver) => { + this.connectResolvers.add(resolver); + this.extension.connect(); + }); + } + + async info() { + return new Promise((...resolver) => { + this.infoResolvers.add(resolver); + this.extension.info(); + }); + } + + disconnect() { + this.connectResolvers.clear(); + this.infoResolvers.clear(); + this.signResolvers.clear(); + } + + async sign({ purgeQueue = true, ...data }: ExtensionOptions) { + return new Promise((...resolver) => { + this._inTransactionProgress = true; + + const id = this.extension.sign({ + ...data, + purgeQueue, + }); + + this.signResolvers.set(id, resolver); + + setTimeout(() => { + if (this.signResolvers.has(id)) { + this.signResolvers.delete(id); + + if (this.signResolvers.size === 0) { + this._inTransactionProgress = false; + } + } + }, 1000 * 120); + }); + } + + private onResponse() { + this.extension.on('onConnect', (result) => { + if (!result) return; + const { error, ...payload } = result; + + for (const [resolve, reject] of this.connectResolvers) { + if (error) { + reject(error); + } else { + resolve(payload); + } + } + + this.connectResolvers.clear(); + }); + + this.extension.on('onInterchainInfo', (result) => { + if (!result) return; + const { error, ...payload } = result; + + for (const [resolve, reject] of this.infoResolvers) { + if (error) { + reject(error); + } else { + resolve(payload); + } + } + + this.infoResolvers.clear(); + }); + + this.extension.on('onSign', (result) => { + if (!result || !isValidResult(result)) { + return; + } + + const { error, ...payload } = result; + + if (this.signResolvers.has(payload.id)) { + const [resolve, reject] = this.signResolvers.get(payload.id)!; + + if (!payload.success) { + reject(error); + } else if (resolve) { + resolve({ name: 'onSign', payload }); + } + + this.signResolvers.delete(payload.id); + + if (this.signResolvers.size === 0) { + this._inTransactionProgress = false; + } + } + }); + } +} diff --git a/wallets/terra-extension/src/extension/index.ts b/wallets/terra-extension/src/extension/index.ts new file mode 100644 index 000000000..f488a5ae7 --- /dev/null +++ b/wallets/terra-extension/src/extension/index.ts @@ -0,0 +1,4 @@ +export * from './chain-wallet'; +export * from './main-wallet'; +export * from './registry'; +export * from './types'; diff --git a/wallets/terra-extension/src/extension/main-wallet.ts b/wallets/terra-extension/src/extension/main-wallet.ts new file mode 100644 index 000000000..496b0a898 --- /dev/null +++ b/wallets/terra-extension/src/extension/main-wallet.ts @@ -0,0 +1,23 @@ +import { Wallet } from '@cosmos-kit/core'; +import { MainWalletBase } from '@cosmos-kit/core'; + +import { ChainTerraExtension } from './chain-wallet'; +import { TerraClient } from './client'; +import { getTerraFromExtension } from './utils'; + +export class TerraExtensionWallet extends MainWalletBase { + constructor(walletInfo: Wallet) { + super(walletInfo, ChainTerraExtension); + } + + async initClient() { + this.initingClient(); + try { + const terra = await getTerraFromExtension(); + this.initClientDone(terra ? new TerraClient(terra) : undefined); + } catch (error) { + this.logger?.error(error); + this.initClientError(error); + } + } +} diff --git a/wallets/terra-extension/src/extension/registry.ts b/wallets/terra-extension/src/extension/registry.ts new file mode 100644 index 000000000..7b6ef379b --- /dev/null +++ b/wallets/terra-extension/src/extension/registry.ts @@ -0,0 +1,29 @@ +import { Wallet } from '@cosmos-kit/core'; +import { GoDesktopDownload } from 'react-icons/go'; +import { RiChromeFill } from 'react-icons/ri'; +import { GrFirefox } from 'react-icons/gr'; + +export const terraExtensionInfo: Wallet = { + name: 'terra-extension', + logo: 'https://assets.terra.money/icon/station-extension/icon.png', + prettyName: 'Terra Station', + mode: 'extension', + mobileDisabled: true, + rejectMessage: { + source: 'Request rejected', + }, + downloads: [ + { + device: 'desktop', + browser: 'chrome', + icon: RiChromeFill, + link: 'https://chrome.google.com/webstore/detail/station-wallet/aiifbnbfobpmeekipheeijimdpnlpgpp', + }, + { + device: 'desktop', + browser: 'firefox', + icon: GrFirefox, + link: 'https://addons.mozilla.org/en-US/firefox/addon/terra-station-wallet/', + }, + ], +}; diff --git a/wallets/terra-extension/src/extension/signer.ts b/wallets/terra-extension/src/extension/signer.ts new file mode 100644 index 000000000..fc98e60a8 --- /dev/null +++ b/wallets/terra-extension/src/extension/signer.ts @@ -0,0 +1,69 @@ +import { AccountData } from '@cosmjs/proto-signing'; +import { + OfflineAminoSigner, + AminoSignResponse, + StdSignDoc, + StdSignature, +} from '@cosmjs/amino'; +import { WalletAccount } from '@cosmos-kit/core'; +import { TerraExtension } from './extension'; +import { + Fee as TerraFee, + Msg as TerraMsg, + SignatureV2, +} from '@terra-money/feather.js'; + +export class OfflineSigner implements OfflineAminoSigner { + private extension: TerraExtension; + accountInfo: WalletAccount; + + constructor(extension: TerraExtension, accountInfo: WalletAccount) { + this.extension = extension; + this.accountInfo = accountInfo; + } + + async getAccounts(): Promise { + return [ + { + address: this.accountInfo.address, + algo: this.accountInfo.algo || 'secp256k1', + pubkey: this.accountInfo.pubkey, + }, + ]; + } + + async signAmino( + signerAddress: string, + signDoc: StdSignDoc + ): Promise { + const signDocFee = signDoc.fee; + const feeAmount = signDocFee.amount[0].amount + signDocFee.amount[0].denom; + const fakeMsgs = signDoc.msgs.map((msg) => + TerraMsg.fromAmino(msg as TerraMsg.Amino) + ); + + const signResponse = await this.extension.sign({ + chainID: signDoc.chain_id, + msgs: fakeMsgs, + fee: new TerraFee( + parseInt(signDocFee.gas), + feeAmount, + signDocFee.payer, + signDocFee.granter + ), + memo: signDoc.memo, + signMode: SignatureV2.SignMode.SIGN_MODE_LEGACY_AMINO_JSON, + } as any); + + const signature: StdSignature = { + pub_key: (signResponse.payload.result.auth_info.signer_infos[0] + .public_key as any).key, + signature: signResponse.payload.result.signatures[0], + }; + + return { + signed: signDoc, + signature, + }; + } +} diff --git a/wallets/terra-extension/src/extension/types.ts b/wallets/terra-extension/src/extension/types.ts new file mode 100644 index 000000000..c2d190420 --- /dev/null +++ b/wallets/terra-extension/src/extension/types.ts @@ -0,0 +1,19 @@ +export type ChainId = string; + +export type Addresses = Record; + +export type CoinType = number; + +export type Pubkeys = Record; + +export interface NetworkInfo { + baseAsset: string; + chainID: string; + coinType: string; + gasAdjustment: number; + gasPrices: Record; + icon: string; + lcd: string; + name: string; + prefix: string; +} diff --git a/wallets/terra-extension/src/extension/utils.ts b/wallets/terra-extension/src/extension/utils.ts new file mode 100644 index 000000000..56b12e626 --- /dev/null +++ b/wallets/terra-extension/src/extension/utils.ts @@ -0,0 +1,24 @@ +import { ClientNotExistError } from '@cosmos-kit/core'; + +import { TerraExtension } from './extension'; + +interface TerraWindow { + isStationExtensionAvailable?: boolean; +} + +export const getTerraFromExtension: () => Promise< + TerraExtension | undefined +> = async () => { + if (typeof window === 'undefined') { + return void 0; + } + + if (!(window as TerraWindow).isStationExtensionAvailable) { + throw ClientNotExistError; + } + + const terraExtension = new TerraExtension(); + await terraExtension.init(); + + return terraExtension; +}; diff --git a/wallets/terra-extension/src/index.ts b/wallets/terra-extension/src/index.ts new file mode 100644 index 000000000..8dba35355 --- /dev/null +++ b/wallets/terra-extension/src/index.ts @@ -0,0 +1,2 @@ +export * from './extension'; +export * from './terra'; diff --git a/wallets/terra-extension/src/terra.ts b/wallets/terra-extension/src/terra.ts new file mode 100644 index 000000000..99b2720df --- /dev/null +++ b/wallets/terra-extension/src/terra.ts @@ -0,0 +1,5 @@ +import { terraExtensionInfo, TerraExtensionWallet } from './extension'; + +const terraExtension = new TerraExtensionWallet(terraExtensionInfo); + +export const wallets = [terraExtension]; diff --git a/wallets/terra-extension/tsconfig.json b/wallets/terra-extension/tsconfig.json new file mode 100644 index 000000000..40d6703dd --- /dev/null +++ b/wallets/terra-extension/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "es2015", + "skipLibCheck": true, + "declaration": true, + "declarationDir": "./types", + "emitDeclarationOnly": true, + "isolatedModules": true, + "allowJs": true, + "esModuleInterop": true, + "downlevelIteration": true, + "moduleResolution": "node" + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/wallets/terra-extension/types/extension/chain-wallet.d.ts b/wallets/terra-extension/types/extension/chain-wallet.d.ts new file mode 100644 index 000000000..e00760e15 --- /dev/null +++ b/wallets/terra-extension/types/extension/chain-wallet.d.ts @@ -0,0 +1,4 @@ +import { ChainRecord, ChainWalletBase, Wallet } from '@cosmos-kit/core'; +export declare class ChainTerraExtension extends ChainWalletBase { + constructor(walletInfo: Wallet, chainInfo: ChainRecord); +} diff --git a/wallets/terra-extension/types/extension/client.d.ts b/wallets/terra-extension/types/extension/client.d.ts new file mode 100644 index 000000000..c149d3d2f --- /dev/null +++ b/wallets/terra-extension/types/extension/client.d.ts @@ -0,0 +1,15 @@ +import { WalletClient, WalletAccount } from '@cosmos-kit/core'; +import { TerraExtension } from './extension'; +import { OfflineSigner } from './signer'; +export declare class TerraClient implements WalletClient { + readonly client: TerraExtension; + constructor(client: TerraExtension); + disconnect(): Promise; + getSimpleAccount(chainId: string): Promise<{ + namespace: string; + chainId: string; + address: string; + }>; + getAccount(chainId: string): Promise; + getOfflineSigner(chainId: string): Promise; +} diff --git a/wallets/terra-extension/types/extension/extension.d.ts b/wallets/terra-extension/types/extension/extension.d.ts new file mode 100644 index 000000000..bb207c91b --- /dev/null +++ b/wallets/terra-extension/types/extension/extension.d.ts @@ -0,0 +1,30 @@ +import { Tx, ExtensionOptions } from '@terra-money/feather.js'; +import { NetworkInfo, Addresses, Pubkeys, ChainId } from './types'; +declare type ConnectResponse = { + address: string; + addresses: Addresses; + pubkey: Pubkeys; +}; +declare type InfoResponse = Record; +declare type SignResponse = { + payload: { + result: Tx.Data; + }; +}; +export declare class TerraExtension { + private extension; + identifier: string; + _inTransactionProgress: boolean; + connectResolvers: Set<[(data: any) => void, (error: any) => void]>; + infoResolvers: Set<[(data: any) => void, (error: any) => void]>; + signResolvers: Map void, (error: any) => void]>; + constructor(); + get isAvailable(): boolean; + init(): Promise; + connect(): Promise; + info(): Promise; + disconnect(): void; + sign({ purgeQueue, ...data }: ExtensionOptions): Promise; + private onResponse; +} +export {}; diff --git a/wallets/terra-extension/types/extension/index.d.ts b/wallets/terra-extension/types/extension/index.d.ts new file mode 100644 index 000000000..f488a5ae7 --- /dev/null +++ b/wallets/terra-extension/types/extension/index.d.ts @@ -0,0 +1,4 @@ +export * from './chain-wallet'; +export * from './main-wallet'; +export * from './registry'; +export * from './types'; diff --git a/wallets/terra-extension/types/extension/main-wallet.d.ts b/wallets/terra-extension/types/extension/main-wallet.d.ts new file mode 100644 index 000000000..22457590c --- /dev/null +++ b/wallets/terra-extension/types/extension/main-wallet.d.ts @@ -0,0 +1,6 @@ +import { Wallet } from '@cosmos-kit/core'; +import { MainWalletBase } from '@cosmos-kit/core'; +export declare class TerraExtensionWallet extends MainWalletBase { + constructor(walletInfo: Wallet); + initClient(): Promise; +} diff --git a/wallets/terra-extension/types/extension/registry.d.ts b/wallets/terra-extension/types/extension/registry.d.ts new file mode 100644 index 000000000..ff2303cbd --- /dev/null +++ b/wallets/terra-extension/types/extension/registry.d.ts @@ -0,0 +1,2 @@ +import { Wallet } from '@cosmos-kit/core'; +export declare const terraExtensionInfo: Wallet; diff --git a/wallets/terra-extension/types/extension/signer.d.ts b/wallets/terra-extension/types/extension/signer.d.ts new file mode 100644 index 000000000..bc0262357 --- /dev/null +++ b/wallets/terra-extension/types/extension/signer.d.ts @@ -0,0 +1,18 @@ +/// +import { AccountData } from '@cosmjs/proto-signing'; +import { OfflineAminoSigner, AminoSignResponse, StdSignDoc } from '@cosmjs/amino'; +import { WalletAccount } from '@cosmos-kit/core'; +import { TerraExtension } from './extension'; +export interface SignDoc { + bodyBytes: Uint8Array; + authInfoBytes: Uint8Array; + chainId: string; + accountNumber: Long; +} +export declare class OfflineSigner implements OfflineAminoSigner { + private extension; + accountInfo: WalletAccount; + constructor(extension: TerraExtension, accountInfo: WalletAccount); + getAccounts(): Promise; + signAmino(signerAddress: string, signDoc: StdSignDoc): Promise; +} diff --git a/wallets/terra-extension/types/extension/types.d.ts b/wallets/terra-extension/types/extension/types.d.ts new file mode 100644 index 000000000..9047ee76e --- /dev/null +++ b/wallets/terra-extension/types/extension/types.d.ts @@ -0,0 +1,17 @@ +export declare type ChainId = string; +export declare type Addresses = { + [k: ChainId]: string; +}; +export declare type CoinType = number; +export declare type Pubkeys = Record; +export interface NetworkInfo { + baseAsset: string; + chainID: string; + coinType: string; + gasAdjustment: number; + gasPrices: Record; + icon: string; + lcd: string; + name: string; + prefix: string; +} diff --git a/wallets/terra-extension/types/extension/utils.d.ts b/wallets/terra-extension/types/extension/utils.d.ts new file mode 100644 index 000000000..04c61d972 --- /dev/null +++ b/wallets/terra-extension/types/extension/utils.d.ts @@ -0,0 +1,2 @@ +import { TerraExtension } from './extension'; +export declare const getTerraFromExtension: () => Promise; diff --git a/wallets/terra-extension/types/index.d.ts b/wallets/terra-extension/types/index.d.ts new file mode 100644 index 000000000..8dba35355 --- /dev/null +++ b/wallets/terra-extension/types/index.d.ts @@ -0,0 +1,2 @@ +export * from './extension'; +export * from './terra'; diff --git a/wallets/terra-extension/types/terra.d.ts b/wallets/terra-extension/types/terra.d.ts new file mode 100644 index 000000000..e9bee9337 --- /dev/null +++ b/wallets/terra-extension/types/terra.d.ts @@ -0,0 +1,2 @@ +import { TerraExtensionWallet } from './extension'; +export declare const wallets: TerraExtensionWallet[]; diff --git a/yarn.lock b/yarn.lock index 201ce6456..e134ace91 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3851,7 +3851,7 @@ "@improbable-eng/grpc-web@^0.14.1": version "0.14.1" - resolved "https://registry.npmjs.org/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz#f4662f64dc89c0f956a94bb8a3b576556c74589c" + resolved "https://registry.yarnpkg.com/@improbable-eng/grpc-web/-/grpc-web-0.14.1.tgz#f4662f64dc89c0f956a94bb8a3b576556c74589c" integrity sha512-XaIYuunepPxoiGVLLHmlnVminUGzBTnXr8Wv7khzmLWbNw4TCwJKX09GSMJlKhu/TRk6gms0ySFxewaETSBqgw== dependencies: browser-headers "^0.4.1" @@ -5772,6 +5772,26 @@ dependencies: tslib "^2.4.0" +"@terra-money/feather.js@^1.0.0-beta.14": + version "1.0.0-beta.15" + resolved "https://registry.yarnpkg.com/@terra-money/feather.js/-/feather.js-1.0.0-beta.15.tgz#d81e31f28428cb23a27bf067eaa7e8f399e9c511" + integrity sha512-KKmwmLemorifApC7y7Rn8H8MzdPmHnTkpqncfHdvWLzhGxeRw0hv24ZPkOj+SOZbhdutwp2RtAH1IEZz23cHUQ== + dependencies: + "@terra-money/legacy.proto" "npm:@terra-money/terra.proto@^0.1.7" + "@terra-money/terra.proto" "^2.2.0-beta.4" + axios "^0.27.2" + bech32 "^2.0.0" + bip32 "^2.0.6" + bip39 "^3.0.3" + bufferutil "^4.0.3" + decimal.js "^10.2.1" + jscrypto "^1.0.1" + readable-stream "^3.6.0" + secp256k1 "^4.0.2" + tmp "^0.2.1" + utf-8-validate "^5.0.5" + ws "^7.5.9" + "@terra-money/feather.js@^1.0.0-beta.4": version "1.0.0-beta.12" resolved "https://registry.npmjs.org/@terra-money/feather.js/-/feather.js-1.0.0-beta.12.tgz#285af7b0fc37551df1d8c15ceae69d87c1bbe23b" @@ -5794,7 +5814,7 @@ "@terra-money/legacy.proto@npm:@terra-money/terra.proto@^0.1.7": version "0.1.7" - resolved "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz#59c18f30da10d43200bab3ba8feb5b17e43a365f" + resolved "https://registry.yarnpkg.com/@terra-money/terra.proto/-/terra.proto-0.1.7.tgz#59c18f30da10d43200bab3ba8feb5b17e43a365f" integrity sha512-NXD7f6pQCulvo6+mv6MAPzhOkUzRjgYVuHZE/apih+lVnPG5hDBU0rRYnOGGofwvKT5/jQoOENnFn/gioWWnyQ== dependencies: google-protobuf "^3.17.3" @@ -5833,7 +5853,7 @@ "@terra-money/terra.proto@^2.2.0-beta.4": version "2.2.0-beta.4" - resolved "https://registry.npmjs.org/@terra-money/terra.proto/-/terra.proto-2.2.0-beta.4.tgz#a5a926dbbd1714511194907ba211e5aee662fd6e" + resolved "https://registry.yarnpkg.com/@terra-money/terra.proto/-/terra.proto-2.2.0-beta.4.tgz#a5a926dbbd1714511194907ba211e5aee662fd6e" integrity sha512-M6ARaIYVPPC08RV9zNLKnTkiyiqAoTM0xugUz0L6YiMsEEnilpY5ju+thlkxcYYKKynO9WFy1zcRRugOw+VlKQ== dependencies: "@improbable-eng/grpc-web" "^0.14.1" @@ -5841,6 +5861,11 @@ long "^4.0.0" protobufjs "~6.11.2" +"@terra-money/wallet-types@^3.11.2": + version "3.11.2" + resolved "https://registry.yarnpkg.com/@terra-money/wallet-types/-/wallet-types-3.11.2.tgz#5be7016abcd249b4839b1aadb837a6aa043dfaf2" + integrity sha512-vIHCqL4gtiAlvhnxDSnh6bTXIIZGNOIEfH/lWEgwCHXp4cGh0MeZixcnd4UvpW2ynirwtWkppAz9N4qX9zTtAA== + "@terra-money/web-extension-interface@^4.0.0": version "4.0.0" resolved "https://registry.npmjs.org/@terra-money/web-extension-interface/-/web-extension-interface-4.0.0.tgz#baf64661aeb4252acb130b15bcb69002674e2de2" @@ -6284,7 +6309,7 @@ "@types/react@18.0.25": version "18.0.25" - resolved "https://registry.npmjs.org/@types/react/-/react-18.0.25.tgz#8b1dcd7e56fe7315535a4af25435e0bb55c8ae44" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.25.tgz#8b1dcd7e56fe7315535a4af25435e0bb55c8ae44" integrity sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g== dependencies: "@types/prop-types" "*" @@ -7856,7 +7881,7 @@ bech32@1.1.4, bech32@^1.1.3, bech32@^1.1.4: bech32@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== before-after-hook@^2.0.0: @@ -8000,7 +8025,7 @@ brorand@^1.1.0: browser-headers@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02" + resolved "https://registry.yarnpkg.com/browser-headers/-/browser-headers-0.4.1.tgz#4308a7ad3b240f4203dbb45acedb38dc2d65dd02" integrity sha512-CA9hsySZVo9371qEHjHZtYxV2cFtVj5Wj/ZHi8ooEsrtm4vOnl9Y9HmyYWk9q+05d7K3rdoAE0j3MVEFVvtQtg== browser-stdout@1.3.1: @@ -8076,7 +8101,7 @@ buffer@~5.4.3: bufferutil@^4.0.1, bufferutil@^4.0.3: version "4.0.7" - resolved "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" + resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" integrity sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw== dependencies: node-gyp-build "^4.3.0" @@ -9030,7 +9055,7 @@ decamelize@^4.0.0: decimal.js@^10.2.1: version "10.4.3" - resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== decode-named-character-reference@^1.0.0: @@ -10702,7 +10727,7 @@ globby@^9.2.0: google-protobuf@^3.17.3: version "3.21.2" - resolved "https://registry.npmjs.org/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4" integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA== gopd@^1.0.1: @@ -12183,7 +12208,7 @@ jsbn@~0.1.0: jscrypto@^1.0.1: version "1.0.3" - resolved "https://registry.npmjs.org/jscrypto/-/jscrypto-1.0.3.tgz#598febca2a939d6f679c54f56e1fe364cef30cc9" + resolved "https://registry.yarnpkg.com/jscrypto/-/jscrypto-1.0.3.tgz#598febca2a939d6f679c54f56e1fe364cef30cc9" integrity sha512-lryZl0flhodv4SZHOqyb1bx5sKcJxj0VBo0Kzb4QMAg3L021IC9uGpl0RCZa+9KJwlRGSK2C80ITcwbe19OKLQ== jsesc@^2.5.1: @@ -13813,7 +13838,7 @@ nice-try@^1.0.4: node-addon-api@^2.0.0: version "2.0.2" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== node-environment-flags@^1.0.5: @@ -13842,7 +13867,7 @@ node-fetch@^2.5.0, node-fetch@^2.6.7: node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: version "4.6.0" - resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" + resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.0.tgz#0c52e4cbf54bbd28b709820ef7b6a3c2d6209055" integrity sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ== node-gyp@^5.0.2: @@ -15577,7 +15602,7 @@ scroll-into-view-if-needed@^2.2.29: secp256k1@^4.0.2: version "4.0.3" - resolved "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" + resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.3.tgz#c4559ecd1b8d3c1827ed2d1b94190d69ce267303" integrity sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA== dependencies: elliptic "^6.5.4" @@ -16456,7 +16481,7 @@ tmp@^0.0.33: tmp@^0.2.1: version "0.2.1" - resolved "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== dependencies: rimraf "^3.0.0" @@ -17027,7 +17052,7 @@ use@^3.1.0: utf-8-validate@^5.0.2, utf-8-validate@^5.0.5: version "5.0.10" - resolved "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" + resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2" integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ== dependencies: node-gyp-build "^4.3.0"