├── .changeset ├── README.md └── config.json ├── .editorconfig ├── .eslintrc.base.yml ├── .eslintrc.js.yml ├── .eslintrc.ts.yml ├── .github └── workflows │ ├── main.yml │ └── near-rewards.yml ├── .gitignore ├── LICENSE ├── README.md ├── buildMoveGuest.sh ├── package.json ├── packages ├── core │ ├── README.md │ ├── lib │ │ ├── index.d.ts │ │ ├── index.js │ │ └── lib │ │ │ ├── balances.d.ts │ │ │ ├── balances.js │ │ │ ├── checks.d.ts │ │ │ ├── checks.js │ │ │ ├── claims.d.ts │ │ │ ├── claims.js │ │ │ ├── drops.d.ts │ │ │ ├── drops.js │ │ │ ├── keypom-utils.d.ts │ │ │ ├── keypom-utils.js │ │ │ ├── keypom.d.ts │ │ │ ├── keypom.js │ │ │ ├── keys.d.ts │ │ │ ├── keys.js │ │ │ ├── sales.d.ts │ │ │ ├── sales.js │ │ │ ├── trial-accounts │ │ │ ├── pre-trial.d.ts │ │ │ ├── pre-trial.js │ │ │ ├── trial-active.d.ts │ │ │ ├── trial-active.js │ │ │ ├── utils.d.ts │ │ │ └── utils.js │ │ │ ├── types │ │ │ ├── drops.d.ts │ │ │ ├── drops.js │ │ │ ├── fc.d.ts │ │ │ ├── fc.js │ │ │ ├── ft.d.ts │ │ │ ├── ft.js │ │ │ ├── general.d.ts │ │ │ ├── general.js │ │ │ ├── nft.d.ts │ │ │ ├── nft.js │ │ │ ├── params.d.ts │ │ │ ├── params.js │ │ │ ├── protocol.d.ts │ │ │ ├── protocol.js │ │ │ ├── simple.d.ts │ │ │ └── simple.js │ │ │ ├── views.d.ts │ │ │ └── views.js │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── balances.ts │ │ │ ├── checks.ts │ │ │ ├── claims.ts │ │ │ ├── drops.ts │ │ │ ├── keypom-utils.ts │ │ │ ├── keypom.ts │ │ │ ├── keys.ts │ │ │ ├── sales.ts │ │ │ ├── trial-accounts │ │ │ ├── pre-trial.ts │ │ │ ├── trial-active.ts │ │ │ └── utils.ts │ │ │ ├── types │ │ │ ├── drops.ts │ │ │ ├── fc.ts │ │ │ ├── ft.ts │ │ │ ├── general.ts │ │ │ ├── nft.ts │ │ │ ├── params.ts │ │ │ ├── protocol.ts │ │ │ └── simple.ts │ │ │ └── views.ts │ ├── test │ │ ├── creation.test.js │ │ ├── dummy-creation.test.js │ │ ├── ext-wasm │ │ │ └── main.wasm │ │ └── instant-sign-in.ts │ ├── tsconfig.json │ └── typedoc.json ├── fastauth │ ├── README.md │ ├── data │ │ ├── clientLog.json │ │ ├── contractLogs.json │ │ ├── signatures.json │ │ └── trialData.json │ ├── deploy │ │ ├── abis │ │ │ ├── baseGuestbook.ts │ │ │ └── baseNFT.ts │ │ ├── broadcastSig.ts │ │ ├── compareLogs.ts │ │ ├── configs │ │ │ ├── evmSimple.ts │ │ │ ├── nearSimple.ts │ │ │ ├── omniChainSimple.ts │ │ │ └── type.ts │ │ ├── main.ts │ │ └── utils │ │ │ ├── evmUtils.ts │ │ │ ├── fileOps.ts │ │ │ ├── logUtils.ts │ │ │ └── nearUtils.ts │ ├── lib │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── lib │ │ │ ├── FastAuthModal.d.ts │ │ │ ├── FastAuthModal.js │ │ │ ├── FastAuthWallet.d.ts │ │ │ ├── FastAuthWallet.js │ │ │ ├── constants.d.ts │ │ │ ├── constants.js │ │ │ ├── icons │ │ │ │ ├── AppleIcon.d.ts │ │ │ │ ├── AppleIcon.js │ │ │ │ ├── CloseIcon.d.ts │ │ │ │ ├── CloseIcon.js │ │ │ │ ├── DiscordIcon.d.ts │ │ │ │ ├── DiscordIcon.js │ │ │ │ ├── GoogleIcon.d.ts │ │ │ │ ├── GoogleIcon.js │ │ │ │ ├── WalletIcon.d.ts │ │ │ │ └── WalletIcon.js │ │ │ ├── modal.d.ts │ │ │ ├── modal.js │ │ │ ├── models │ │ │ │ ├── payload.d.ts │ │ │ │ └── payload.js │ │ │ ├── setupWalletSelector.d.ts │ │ │ ├── setupWalletSelector.js │ │ │ └── utils │ │ │ │ ├── crypto.d.ts │ │ │ │ └── crypto.js │ │ └── styles.css │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── lib │ │ │ ├── FastAuthModal.tsx │ │ │ ├── FastAuthWallet.ts │ │ │ ├── Storage.ts │ │ │ ├── constants.ts │ │ │ ├── icons │ │ │ ├── AppleIcon.tsx │ │ │ ├── CloseIcon.tsx │ │ │ ├── DiscordIcon.tsx │ │ │ ├── GoogleIcon.tsx │ │ │ └── WalletIcon.tsx │ │ │ ├── modal.tsx │ │ │ ├── models │ │ │ └── payload.ts │ │ │ ├── mpcUtils │ │ │ ├── kdf.ts │ │ │ ├── mockSign.ts │ │ │ └── utils.ts │ │ │ ├── setupWalletSelector.ts │ │ │ ├── styles.css │ │ │ └── utils │ │ │ ├── authTokens.ts │ │ │ └── crypto.ts │ ├── tsconfig.json │ └── typedoc.json ├── one-click-connect │ ├── README.md │ ├── lib │ │ ├── core │ │ │ ├── ext_wallets.d.ts │ │ │ ├── ext_wallets.js │ │ │ ├── setup.d.ts │ │ │ ├── setup.js │ │ │ ├── types.d.ts │ │ │ ├── types.js │ │ │ ├── wallet.d.ts │ │ │ └── wallet.js │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── tsconfig.tsbuildinfo │ │ └── utils │ │ │ ├── one-click-utils.d.ts │ │ │ ├── one-click-utils.js │ │ │ ├── selector-utils.d.ts │ │ │ └── selector-utils.js │ ├── package.json │ ├── src │ │ ├── core │ │ │ ├── ext_wallets.ts │ │ │ ├── setup.ts │ │ │ ├── types.ts │ │ │ └── wallet.ts │ │ ├── index.ts │ │ └── utils │ │ │ └── selector-utils.ts │ ├── test │ │ ├── ext-wasm │ │ │ └── trial-accounts.wasm │ │ └── trial-accounts.ts │ ├── tsconfig.json │ └── typedoc.json └── trial-accounts │ ├── README.md │ ├── data │ ├── clientLog.json │ ├── contractLogs.json │ ├── signatures.json │ └── trialData.json │ ├── deploy │ ├── abis │ │ ├── baseGuestbook.ts │ │ └── baseNFT.ts │ ├── broadcastSig.ts │ ├── compareLogs.ts │ ├── configs │ │ ├── evmSimple.ts │ │ ├── nearSimple.ts │ │ ├── omniChainSimple.ts │ │ └── type.ts │ ├── main.ts │ └── utils │ │ ├── evmUtils.ts │ │ ├── fileOps.ts │ │ ├── logUtils.ts │ │ └── nearUtils.ts │ ├── lib │ ├── index.d.ts │ ├── index.js │ └── lib │ │ ├── TrialAccountManager.d.ts │ │ ├── TrialAccountManager.js │ │ ├── activateTrial.d.ts │ │ ├── activateTrial.js │ │ ├── addTrialKeys.d.ts │ │ ├── addTrialKeys.js │ │ ├── broadcastTransaction.d.ts │ │ ├── broadcastTransaction.js │ │ ├── createTrial.d.ts │ │ ├── createTrial.js │ │ ├── cryptoUtils.d.ts │ │ ├── cryptoUtils.js │ │ ├── evmUtils.d.ts │ │ ├── evmUtils.js │ │ ├── logUtils.d.ts │ │ ├── logUtils.js │ │ ├── mpcUtils │ │ ├── kdf.d.ts │ │ └── kdf.js │ │ ├── networks │ │ ├── near.d.ts │ │ └── near.js │ │ ├── performAction.d.ts │ │ ├── performAction.js │ │ ├── types │ │ ├── ActionToPerform.d.ts │ │ ├── ActionToPerform.js │ │ ├── BigInts.d.ts │ │ ├── BigInts.js │ │ ├── Chain.d.ts │ │ ├── Chain.js │ │ ├── ChainConstraints.d.ts │ │ ├── ChainConstraints.js │ │ ├── Constraints.d.ts │ │ ├── Constraints.js │ │ ├── EVMTypes.d.ts │ │ ├── EVMTypes.js │ │ ├── KeyData.d.ts │ │ ├── KeyData.js │ │ ├── KeyUsage.d.ts │ │ ├── KeyUsage.js │ │ ├── MPCSignature.d.ts │ │ ├── MPCSignature.js │ │ ├── TrialAccountInfo.d.ts │ │ ├── TrialAccountInfo.js │ │ ├── TrialData.d.ts │ │ ├── TrialData.js │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── util.d.ts │ │ └── util.js │ │ ├── validityChecker.d.ts │ │ ├── validityChecker.js │ │ └── wallet-selector │ │ ├── setup.d.ts │ │ ├── setup.js │ │ ├── types.d.ts │ │ ├── types.js │ │ ├── wallet.d.ts │ │ └── wallet.js │ ├── package.json │ ├── src │ ├── index.ts │ └── lib │ │ ├── TrialAccountManager.ts │ │ ├── activateTrial.ts │ │ ├── addTrialKeys.ts │ │ ├── broadcastTransaction.ts │ │ ├── createTrial.ts │ │ ├── cryptoUtils.ts │ │ ├── evmUtils.ts │ │ ├── logUtils.ts │ │ ├── mpcUtils │ │ ├── kdf.ts │ │ ├── mockSign.ts │ │ └── utils.ts │ │ ├── networks │ │ ├── constants.ts │ │ ├── evm.ts │ │ ├── index.ts │ │ ├── near.ts │ │ └── types.ts │ │ ├── performAction.ts │ │ ├── types │ │ ├── ActionToPerform.ts │ │ ├── BigInts.ts │ │ ├── Chain.ts │ │ ├── ChainConstraints.ts │ │ ├── Constraints.ts │ │ ├── EVMTypes.ts │ │ ├── KeyData.ts │ │ ├── KeyUsage.ts │ │ ├── MPCSignature.ts │ │ ├── TrialAccountInfo.ts │ │ ├── TrialData.ts │ │ ├── index.ts │ │ └── util.ts │ │ ├── validityChecker.ts │ │ └── wallet-selector │ │ ├── setup.ts │ │ ├── types.ts │ │ └── wallet.ts │ ├── tsconfig.json │ └── typedoc.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── static └── claim-linkdrop-asset.png ├── tsconfig.base.json ├── tsconfig.browser.json ├── tsconfig.node.json └── turbo.json /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://EditorConfig.org 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | -------------------------------------------------------------------------------- /.eslintrc.base.yml: -------------------------------------------------------------------------------- 1 | env: 2 | es6: true 3 | node: true 4 | extends: 5 | - 'eslint:recommended' 6 | parserOptions: 7 | ecmaVersion: 2018 8 | sourceType: module 9 | rules: 10 | indent: 11 | - error 12 | - 4 13 | - SwitchCase: 1 14 | linebreak-style: 15 | - error 16 | - unix 17 | quotes: 18 | - error 19 | - single 20 | semi: 21 | - error 22 | - always 23 | no-console: off 24 | globals: 25 | window: true 26 | fetch: true 27 | Headers: true 28 | document: true 29 | -------------------------------------------------------------------------------- /.eslintrc.js.yml: -------------------------------------------------------------------------------- 1 | extends: './.eslintrc.base.yml' 2 | env: 3 | jest: true 4 | globals: 5 | jasmine: true 6 | window: false 7 | fail: true 8 | -------------------------------------------------------------------------------- /.eslintrc.ts.yml: -------------------------------------------------------------------------------- 1 | extends: 2 | - './.eslintrc.base.yml' 3 | - 'plugin:@typescript-eslint/eslint-recommended' 4 | - 'plugin:@typescript-eslint/recommended' 5 | parser: '@typescript-eslint/parser' 6 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | types: 4 | - closed 5 | 6 | jobs: 7 | if_merged: 8 | if: github.event.pull_request.merged == true 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Install Deps 12 | run: npm install 13 | - name: Build Documentation 14 | run: npm run build-docs && cd .. 15 | - name: Clone Docs Repo 16 | uses: actions/checkout@master 17 | with: 18 | repository: keypom/keypom-docs 19 | token: ${{ secrets.PAT }} 20 | - name: Install Deps 21 | run: cd keypom-docs && npm install 22 | - name: Build TypeDocs 23 | run: npm run build:typedocs 24 | - name: Create Pull Request 25 | uses: peter-evans/create-pull-request@v4.2.3 26 | with: 27 | token: ${{ secrets.PAT }} 28 | -------------------------------------------------------------------------------- /.github/workflows/near-rewards.yml: -------------------------------------------------------------------------------- 1 | name: NEAR Protocol Rewards Tracking 2 | on: 3 | schedule: 4 | - cron: '0 */12 * * *' # Every 12 hours 5 | workflow_dispatch: # Manual trigger 6 | push: 7 | branches: [ main ] # Start on main branch updates 8 | 9 | jobs: 10 | calculate-rewards: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: read 14 | issues: read 15 | pull-requests: read 16 | steps: 17 | - uses: actions/checkout@v3 18 | - uses: actions/setup-node@v3 19 | with: 20 | node-version: '18' 21 | 22 | - name: Calculate Rewards 23 | env: 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | GITHUB_REPO: ${{ github.repository }} 26 | run: npx near-protocol-rewards calculate 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | # Developer note: near.gitignore will be renamed to .gitignore upon project creation 3 | # dependencies 4 | node_modules 5 | yarn.lock 6 | /.pnp 7 | .pnp.js 8 | /out 9 | notes 10 | 11 | docs/ 12 | 13 | *_links.json 14 | 15 | #IDE 16 | .idea 17 | .vscode 18 | 19 | storage 20 | 21 | *.map 22 | 23 | dist/ 24 | 25 | # near-api-js files & coverage 26 | .nyc_output 27 | src\.ts/protos\.d\.ts 28 | package\-lock\.json 29 | 30 | # OS X 31 | .DS_Store 32 | 33 | # Generated test files 34 | test-keys/ 35 | 36 | .turbo 37 | 38 | #keys 39 | /neardev 40 | 41 | #cache 42 | .cache 43 | .parcel-cache 44 | target 45 | 46 | # testing 47 | /coverage 48 | 49 | # production 50 | dist/ 51 | 52 | # misc 53 | .DS_Store 54 | .env 55 | .env.local 56 | .env.development.local 57 | .env.test.local 58 | .env.production.local 59 | buildMove.sh 60 | 61 | npm-debug.log* 62 | yarn-debug.log* 63 | yarn-error.log* 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 4 | 5 | 6 |

Keypom JavaScript SDK

7 | 8 |

9 | 10 |

11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |

24 | 25 | --- 26 | 27 | 28 | > To view our Eth DENVER talk, click [here](https://youtu.be/oHj-GjFi6g4). 29 | > To read more about the Keypom Protocol, refer to the [official GitHub repository](https://github.com/keypom/keypom#about) 30 | 31 | # Getting Started 32 | 33 | The Keypom SDK comes in two parts: 34 | 1. The Core SDK 35 | 2. The Keypom Wallet Selector 36 | 37 | To get started with the Core SDK, refer to our [starting guide](https://github.com/keypom/keypom-js/tree/main/packages/core/README.md). 38 | 39 | Similarly, a getting started guide for the Keypom Wallet Selector can be found [here](https://github.com/keypom/keypom-js/tree/main/packages/selector/README.md). 40 | 41 | # Documentation 42 | 43 | Visit our [documentation](https://docs.keypom.xyz/) for more information on the Keypom Protocol and the Keypom SDK. 44 | 45 | # Contributing 46 | 47 | First off, thanks for taking the time to contribute! Contributions are what makes the open-source community such an amazing place to learn, inspire, and create. Any contributions you make will benefit everybody else and are **greatly appreciated**. 48 | 49 | Please try to create bug reports that are: 50 | 51 | - _Reproducible._ Include steps to reproduce the problem. 52 | - _Specific._ Include as much detail as possible: which version, what environment, etc. 53 | - _Unique._ Do not duplicate existing opened issues. 54 | - _Scoped to a Single Bug._ One bug per report. 55 | 56 | You can use [markdownlint-cli](https://github.com/igorshubovych/markdownlint-cli) to check for common markdown style inconsistency. 57 | 58 | # License 59 | 60 | This project is licensed under the **GPL License**. -------------------------------------------------------------------------------- /buildMoveGuest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Variables 4 | source_folder="/Users/min/Documents/NEAR_Stuff/keypom-js/packages/one-click-connect" # Replace with the name of the folder to copy 5 | destination_folder="one-click-connect" # Replace with the name of the folder to delete 6 | destination_directory="/Users/min/Documents/NEAR_Stuff/guest-book-examples/frontend/node_modules/@keypom" # Replace with the path to the directory containing the folder to delete 7 | 8 | # Step 1: Copy the folder in the current directory 9 | cp -r "$source_folder" /tmp/copied_folder 10 | 11 | # Step 2: Delete the folder from a different directory 12 | rm -rf "$destination_directory/$destination_folder" 13 | 14 | # Step 3: Paste the copied folder in the deleted folder's directory 15 | mv /tmp/copied_folder "$destination_directory/$destination_folder" 16 | 17 | # Optional: Print a message indicating the operation is complete 18 | echo "Folder '$source_folder' has been copied to '$destination_directory' as '$destination_folder'" -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@keypom-js/monorepo", 3 | "author": "benkurrek, mattlockyer", 4 | "private": true, 5 | "engines": { 6 | "node": ">=16.14.0", 7 | "pnpm": ">=7" 8 | }, 9 | "scripts": { 10 | "preinstall": "npx only-allow pnpm", 11 | "build": "turbo run build", 12 | "clean": "turbo run clean", 13 | "lint": "turbo run lint:ts", 14 | "lint:fix": "turbo run lint:ts:fix", 15 | "autoclave": "rimraf packages/**/dist && rimraf packages/**/lib && rimraf packages/**/node_modules && rimraf packages/**/coverage && rimraf packages/**/.turbo && rm -rf node_modules", 16 | "test": "turbo run test", 17 | "release": "changeset publish", 18 | "prepare": "husky install" 19 | }, 20 | "dependencies": { 21 | "borsh": "^0.7.0" 22 | }, 23 | "devDependencies": { 24 | "@changesets/changelog-github": "^0.4.6", 25 | "@changesets/cli": "^2.24.4", 26 | "@commitlint/cli": "^17.0.3", 27 | "@types/node": "^22.7.5", 28 | "@commitlint/config-conventional": "^17.0.3", 29 | "@typescript-eslint/eslint-plugin": "^5.31.0", 30 | "@typescript-eslint/parser": "^5.31.0", 31 | "commitlint": "^17.0.3", 32 | "eslint": "^8.20.0", 33 | "husky": "^7.0.4", 34 | "rimraf": "^3.0.2", 35 | "turbo": "^1.4.5", 36 | "typescript": "^4.9.4", 37 | "typedoc": "^0.24.7" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/core/lib/index.d.ts: -------------------------------------------------------------------------------- 1 | export { addToBalance, withdrawBalance } from "./lib/balances"; 2 | export { claim } from "./lib/claims"; 3 | export { createDrop, deleteDrops } from "./lib/drops"; 4 | export { 5 | /** @group Utility */ 6 | execute, getEnv, initKeypom, networks, accountMappingContract, supportedKeypomContracts, supportedLinkdropClaimPages, updateFunder, updateKeypomContractId, } from "./lib/keypom"; 7 | export { viewAccessKeyData, generatePerUsePasswords, convertBasicTransaction, accountExists, createNFTSeries, estimateRequiredDeposit, formatLinkdropUrl, ftTransferCall, generateKeys, getFTMetadata, getNFTMetadata, getPubFromSecret, getStorageBase, hashPassword, nftTransferCall, } from "./lib/keypom-utils"; 8 | export { addKeys, deleteKeys } from "./lib/keys"; 9 | export * from "./lib/sales"; 10 | export { claimTrialAccountDrop, createTrialAccountDrop, } from "./lib/trial-accounts/pre-trial"; 11 | export { canExitTrial, trialCallMethod, trialSignAndSendTxns, } from "./lib/trial-accounts/trial-active"; 12 | export { wrapTxnParamsForTrial, isUnclaimedTrialDrop, TRIAL_ERRORS, } from "./lib/trial-accounts/utils"; 13 | export * from "./lib/types/drops"; 14 | export * from "./lib/types/fc"; 15 | export * from "./lib/types/ft"; 16 | export * from "./lib/types/general"; 17 | export * from "./lib/types/nft"; 18 | export * from "./lib/types/params"; 19 | export * from "./lib/types/protocol"; 20 | export * from "./lib/types/simple"; 21 | export * from "./lib/views"; 22 | -------------------------------------------------------------------------------- /packages/core/lib/lib/balances.d.ts: -------------------------------------------------------------------------------- 1 | import { Account } from "@near-js/accounts"; 2 | import { AnyWallet } from "./types/params"; 3 | /** 4 | * Deposit some amount of $NEAR or yoctoNEAR$ into the Keypom contract. This amount can then be used to create drops or add keys without 5 | * Having to explicitly attach a deposit everytime. It can be thought of like a bank account. 6 | * 7 | * @example 8 | * Add 1 $NEAR to the account balance 9 | * ```js 10 | * // Initialize the SDK on testnet 11 | * await initKeypom({ 12 | * network: "testnet", 13 | * funder: { 14 | * accountId: "benji_demo.testnet", 15 | * secretKey: "ed25519:5yARProkcALbxaSQ66aYZMSBPWL9uPBmkoQGjV3oi2ddQDMh1teMAbz7jqNV9oVyMy7kZNREjYvWPqjcA6LW9Jb1" 16 | * } 17 | * }); 18 | * 19 | * await addToBalance({ 20 | * amount: "1", 21 | * )}; 22 | * ``` 23 | * @group User Balance Functions 24 | */ 25 | export declare const addToBalance: ({ account, wallet, amountNear, amountYocto, successUrl, }: { 26 | /** Account object that if passed in, will be used to sign the txn instead of the funder account. */ 27 | account?: Account; 28 | /** If using a browser wallet through wallet selector and that wallet should sign the transaction, pass in the object. */ 29 | wallet?: AnyWallet; 30 | /** 31 | * Amount of tokens to add but considering the decimal amount (non human-readable). 32 | * @example 33 | * Transferring one $NEAR should be passed in as "1000000000000000000000000" and NOT "1" 34 | */ 35 | amountYocto?: string; 36 | /** 37 | * Human readable format for the amount of tokens to add. 38 | * @example 39 | * Example: transferring one $NEAR should be passed in as "1" and NOT "1000000000000000000000000" 40 | */ 41 | amountNear?: string; 42 | /** When signing with a wallet, a success URl can be included that the user will be redirected to once the transaction has been successfully signed. */ 43 | successUrl?: string; 44 | }) => Promise; 45 | /** 46 | * Withdraw all the $NEAR from your balance in the Keypom contract. 47 | * 48 | * @example 49 | * Add 1 $NEAR to the account balance and then withdraw it 50 | * ```js 51 | * // Initialize the SDK on testnet 52 | * await initKeypom({ 53 | * network: "testnet", 54 | * funder: { 55 | * accountId: "benji_demo.testnet", 56 | * secretKey: "ed25519:5yARProkcALbxaSQ66aYZMSBPWL9uPBmkoQGjV3oi2ddQDMh1teMAbz7jqNV9oVyMy7kZNREjYvWPqjcA6LW9Jb1" 57 | * } 58 | * }); 59 | * 60 | * await addToBalance({ 61 | * amount: "1", 62 | * }); 63 | * 64 | * await withdrawBalance({}); 65 | * ``` 66 | * @group User Balance Functions 67 | */ 68 | export declare const withdrawBalance: ({ account, wallet, }: { 69 | /** Account object that if passed in, will be used to sign the txn instead of the funder account. */ 70 | account?: Account; 71 | /** If using a browser wallet through wallet selector and that wallet should sign the transaction, pass in the object. */ 72 | wallet?: AnyWallet; 73 | }) => Promise; 74 | -------------------------------------------------------------------------------- /packages/core/lib/lib/checks.d.ts: -------------------------------------------------------------------------------- 1 | import { Account } from "@near-js/accounts"; 2 | import { Near } from "@near-js/wallet-account"; 3 | import { FCData } from "./types/fc"; 4 | import { Funder } from "./types/general"; 5 | import { ProtocolReturnedDropConfig } from "./types/protocol"; 6 | export declare function isValidKeypomContract(keypomContractId: string): boolean; 7 | export declare function isSupportedKeypomContract(keypomContractId: string): boolean; 8 | export declare function isValidAccountObj(o: Account | undefined): o is Account; 9 | export declare function isValidNearObject(o: Near): o is Near; 10 | export declare function isValidFunderObject(o: Funder): o is Funder; 11 | export declare const assert: (exp: any, m: any) => void; 12 | export declare const assertValidDropConfig: (config?: ProtocolReturnedDropConfig) => void; 13 | export declare const assertValidFCData: (fcData: FCData | undefined, usesPerKey: number) => void; 14 | export declare const assertDropIdUnique: (dropId: string) => Promise; 15 | -------------------------------------------------------------------------------- /packages/core/lib/lib/trial-accounts/utils.d.ts: -------------------------------------------------------------------------------- 1 | import { Transaction } from "@near-wallet-selector/core"; 2 | export declare const TRIAL_ERRORS: { 3 | EXIT_EXPECTED: string; 4 | INVALID_ACTION: string; 5 | INSUFFICIENT_BALANCE: string; 6 | }; 7 | export declare const validateDesiredMethods: ({ methodData, trialAccountId, }: { 8 | methodData: { 9 | receiverId: string; 10 | methodName: string; 11 | deposit: string; 12 | }[]; 13 | trialAccountId: string; 14 | }) => Promise; 15 | export declare const wrapTxnParamsForTrial: (params: any, newParams?: {}) => {}; 16 | export declare const generateExecuteArgs: ({ desiredTxns, }: { 17 | /** The transactions to execute */ 18 | desiredTxns: Transaction[]; 19 | }) => { 20 | totalAttachedYocto: any; 21 | totalGasForTxns: any; 22 | executeArgs: any; 23 | methodDataToValidate: any; 24 | }; 25 | export declare const estimateTrialGas: ({ executeArgs, }: { 26 | executeArgs: { 27 | transactions: { 28 | "|kR|": string; 29 | /** The actions to execute */ 30 | actions: { 31 | /** The type of action to execute */ 32 | "|kA|": "FunctionCall"; 33 | /** The parameters for the action */ 34 | params: { 35 | /** The method name to execute */ 36 | "|kP|methodName": string; 37 | /** The arguments to pass to the method */ 38 | "|kP|args": string; 39 | /** The amount of gas to attach to the transaction */ 40 | "|kP|gas": string; 41 | /** The amount of NEAR to attach to the transaction */ 42 | "|kP|deposit": string; 43 | }; 44 | }[]; 45 | }[]; 46 | }; 47 | }) => any; 48 | export declare const isUnclaimedTrialDrop: ({ keypomContractId, secretKey }: { 49 | keypomContractId: any; 50 | secretKey: any; 51 | }) => Promise; 52 | export declare const hasEnoughBalance: ({ trialAccountId, totalGasForTxns, totalAttachedYocto, }: { 53 | trialAccountId: string; 54 | totalGasForTxns: string; 55 | totalAttachedYocto: string; 56 | }) => Promise; 57 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/drops.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/fc.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/ft.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Information pertaining to all Fungible-Token drops. This should be passed in if the drop will be used to transfer any fungible tokens. 3 | */ 4 | export interface FTData { 5 | /** 6 | * Which contract do the FTs belong to? 7 | */ 8 | contractId: string; 9 | /** 10 | * By default, anyone can fund your drop with FTs. This field allows you to set a specific account ID that will be locked into sending the FTs. 11 | */ 12 | senderId?: string; 13 | /** 14 | * Human readable format for the amount of tokens to transfer everytime the FT key is used. 15 | * Example: transferring one wNEAR should be passed in as "1" and NOT "1000000000000000000000000" 16 | */ 17 | amount?: string; 18 | /** 19 | * Amount of tokens to transfer but considering the decimal amount. 20 | * Example: transferring one wNEAR should be passed in as "1000000000000000000000000" and NOT "1" 21 | */ 22 | absoluteAmount?: string; 23 | } 24 | /** 25 | * General structure of Fungible Token Metadata as per official NEP-148 standard (https://github.com/near/NEPs/blob/master/neps/nep-0148.md). 26 | */ 27 | export interface FungibleTokenMetadata { 28 | /** A string. Should be ft-1.0.0 to indicate that a Fungible Token contract adheres to the current versions of this Metadata and the Fungible Token Core specs. This will allow consumers of the Fungible Token to know if they support the features of a given contract. */ 29 | spec: string; 30 | /** The human-readable name of the token. */ 31 | name: string; 32 | /** The abbreviation, like wETH or AMPL. */ 33 | symbol: string; 34 | /** Used in frontends to show the proper significant digits of a token. This concept is explained well in this OpenZeppelin post (https://docs.openzeppelin.com/contracts/3.x/erc20#a-note-on-decimals). */ 35 | decimals: number; 36 | /** 37 | * A small image associated with this token. Must be a data URL, to help consumers display it quickly while protecting user data. 38 | * Recommendation: use optimized SVG, which can result in high-resolution images with only 100s of bytes of storage cost. 39 | * (Note that these storage costs are incurred to the token owner/deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) 40 | * Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by embedding media queries in the SVG. 41 | */ 42 | icon?: string; 43 | /** A link to a valid JSON file containing various keys offering supplementary details on the token. Example: /ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm, https://example.com/token.json, etc. If the information given in this document conflicts with the on-chain attributes, the values in reference shall be considered the source of truth. */ 44 | reference?: string; 45 | /** The base64-encoded sha256 hash of the JSON file contained in the reference field. This is to guard against off-chain tampering. */ 46 | reference_hash?: string; 47 | } 48 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/ft.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/general.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | //import { Account, Connection, Near } from "near-api-js"; 3 | //import { KeyStore } from "near-api-js/lib/key_stores"; 4 | //import { KeyPair } from "near-api-js/lib/utils"; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/nft.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/params.d.ts: -------------------------------------------------------------------------------- 1 | import { Maybe } from "../keypom"; 2 | import { PasswordPerUse } from "./drops"; 3 | import { GeneratedKeyPairs } from "./general"; 4 | import { ProtocolReturnedDropConfig, ProtocolReturnedFCData, ProtocolReturnedFTData, ProtocolReturnedNFTData, ProtocolReturnedSimpleData } from "./protocol"; 5 | import { Account } from "@near-js/accounts"; 6 | import { Transaction } from "@near-js/transactions"; 7 | import { BrowserWalletBehaviour } from "@near-wallet-selector/core"; 8 | import { Wallet } from "@near-wallet-selector/core"; 9 | export type AnyWallet = BrowserWalletBehaviour | Wallet | Promise; 10 | /** 11 | * Information returned when creating a drop or adding keys via `createDrop` and `addKeys` respectively. 12 | */ 13 | export interface CreateOrAddReturn { 14 | /** The responses to any transactions that were signed and sent to the network. */ 15 | responses?: any; 16 | /** Information about the transactions if `returnTransactions` is specified in the arguments. This will result in the information being returned instead of signed and sent. */ 17 | transactions?: Transaction[]; 18 | /** The required deposit that should be attached to the transaction. */ 19 | requiredDeposit?: string; 20 | /** Any keys that were automatically generated. */ 21 | keys?: GeneratedKeyPairs; 22 | /** The drop ID for the drop that is being interacted with. */ 23 | dropId: string; 24 | } 25 | /** 26 | * @ignore 27 | */ 28 | export interface RegisterUsesParams { 29 | account?: Account; 30 | wallet?: AnyWallet; 31 | dropId: string; 32 | numUses: number; 33 | useBalance?: boolean; 34 | } 35 | /** @internal */ 36 | export interface CreateDropProtocolArgs { 37 | public_keys?: string[]; 38 | deposit_per_use: string; 39 | drop_id?: string; 40 | config?: ProtocolReturnedDropConfig; 41 | metadata?: string; 42 | required_gas?: string; 43 | simple?: ProtocolReturnedSimpleData; 44 | ft?: ProtocolReturnedFTData; 45 | nft?: ProtocolReturnedNFTData; 46 | fc?: ProtocolReturnedFCData; 47 | passwords_per_use?: Array>>; 48 | } 49 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/params.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/protocol.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/simple.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Specific configurable information for Simple drops. 3 | */ 4 | export interface SimpleData { 5 | /** If this is set to true, keys can be created and registered AFTER they've been created (for simple and FC drops only). */ 6 | lazyRegister?: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/lib/lib/types/simple.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@keypom/core", 3 | "version": "1.0.6", 4 | "description": "Core library for interacting with the Keypom Protocol", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "pnpm compile", 8 | "compile": "tsc -p tsconfig.json", 9 | "lint:js": "eslint -c ../../.eslintrc.js.yml src/**/*.js --no-eslintrc", 10 | "lint:js:fix": "eslint -c ../../.eslintrc.js.yml src/**/*.js --no-eslintrc --fix", 11 | "lint:ts": "eslint -c ../../.eslintrc.ts.yml src/**/*.ts --no-eslintrc", 12 | "lint:ts:fix": "eslint -c ../../.eslintrc.ts.yml src/**/*.ts --no-eslintrc --fix", 13 | "test": "yarn test:main && yarn test:trial-accounts && yarn test:drop-creation && yarn test:dummy-creation", 14 | "test:drop-creation": "yarn build && yarn ava:drop-creation", 15 | "test:dummy-creation": "yarn build && yarn ava:dummy-creation", 16 | "ava:drop-creation": "ava test/creation.test.js -vs --timeout=5m", 17 | "ava:dummy-creation": "ava test/dummy-creation.test.js -vs --timeout=5m", 18 | "build-docs": "npx typedoc --options typedoc.json" 19 | }, 20 | "author": "benkurrek, mattlockyer", 21 | "license": "MIT", 22 | "dependencies": { 23 | "@near-wallet-selector/core": "^8.9.7", 24 | "bn.js": "^5.2.1", 25 | "borsh": "^0.7.0", 26 | "near-seed-phrase": "^0.2.0", 27 | "util": "^0.12.5" 28 | }, 29 | "ava": { 30 | "require": [ 31 | "dotenv/config" 32 | ] 33 | }, 34 | "devDependencies": { 35 | "@near-js/accounts": "^1.2.0", 36 | "@near-js/crypto": "^1.2.3", 37 | "@near-js/keystores-browser": "^0.0.11", 38 | "@near-js/keystores-node": "^0.0.11", 39 | "@near-js/transactions": "^1.2.1", 40 | "@near-js/providers": "^0.2.1", 41 | "@near-js/types": "^0.2.0", 42 | "@near-js/utils": "^0.2.1", 43 | "@near-js/wallet-account": "^1.2.1", 44 | "@near-js/keystores": "^0.0.11", 45 | "ava": "^4.3.3", 46 | "eslint": "^8.39.0", 47 | "typedoc": "^0.23.24", 48 | "typescript": "^4.8.4" 49 | }, 50 | "peerDependencies": { 51 | "@near-js/accounts": "^1.2.0", 52 | "@near-js/crypto": "^1.2.3", 53 | "@near-js/keystores-browser": "^0.0.11", 54 | "@near-js/transactions": "^1.2.1", 55 | "@near-js/keystores": "^0.0.11", 56 | "@near-js/types": "^0.2.0", 57 | "@near-js/providers": "^0.2.1", 58 | "@near-js/utils": "^0.2.1", 59 | "@near-js/wallet-account": "^1.2.1" 60 | }, 61 | "files": [ 62 | "lib" 63 | ] 64 | } 65 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export { addToBalance, withdrawBalance } from "./lib/balances"; 2 | export { claim } from "./lib/claims"; 3 | export { createDrop, deleteDrops } from "./lib/drops"; 4 | export { 5 | /** @group Utility */ 6 | execute, 7 | getEnv, 8 | initKeypom, 9 | networks, 10 | accountMappingContract, 11 | supportedKeypomContracts, 12 | supportedLinkdropClaimPages, 13 | updateFunder, 14 | updateKeypomContractId, 15 | } from "./lib/keypom"; 16 | export { 17 | viewAccessKeyData, 18 | generatePerUsePasswords, 19 | convertBasicTransaction, 20 | accountExists, 21 | createNFTSeries, 22 | estimateRequiredDeposit, 23 | formatLinkdropUrl, 24 | ftTransferCall, 25 | generateKeys, 26 | getFTMetadata, 27 | getNFTMetadata, 28 | getPubFromSecret, 29 | getStorageBase, 30 | hashPassword, 31 | nftTransferCall, 32 | } from "./lib/keypom-utils"; 33 | export { addKeys, deleteKeys } from "./lib/keys"; 34 | export * from "./lib/sales"; 35 | export { 36 | claimTrialAccountDrop, 37 | createTrialAccountDrop, 38 | } from "./lib/trial-accounts/pre-trial"; 39 | export { 40 | canExitTrial, 41 | trialCallMethod, 42 | trialSignAndSendTxns, 43 | } from "./lib/trial-accounts/trial-active"; 44 | export { 45 | wrapTxnParamsForTrial, 46 | isUnclaimedTrialDrop, 47 | TRIAL_ERRORS, 48 | } from "./lib/trial-accounts/utils"; 49 | export * from "./lib/types/drops"; 50 | export * from "./lib/types/fc"; 51 | export * from "./lib/types/ft"; 52 | export * from "./lib/types/general"; 53 | export * from "./lib/types/nft"; 54 | export * from "./lib/types/params"; 55 | export * from "./lib/types/protocol"; 56 | export * from "./lib/types/simple"; 57 | export * from "./lib/views"; 58 | -------------------------------------------------------------------------------- /packages/core/src/lib/types/ft.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Information pertaining to all Fungible-Token drops. This should be passed in if the drop will be used to transfer any fungible tokens. 3 | */ 4 | export interface FTData { 5 | /** 6 | * Which contract do the FTs belong to? 7 | */ 8 | contractId: string; 9 | /** 10 | * By default, anyone can fund your drop with FTs. This field allows you to set a specific account ID that will be locked into sending the FTs. 11 | */ 12 | senderId?: string; 13 | /** 14 | * Human readable format for the amount of tokens to transfer everytime the FT key is used. 15 | * Example: transferring one wNEAR should be passed in as "1" and NOT "1000000000000000000000000" 16 | */ 17 | amount?: string; 18 | /** 19 | * Amount of tokens to transfer but considering the decimal amount. 20 | * Example: transferring one wNEAR should be passed in as "1000000000000000000000000" and NOT "1" 21 | */ 22 | absoluteAmount?: string; 23 | } 24 | 25 | /** 26 | * General structure of Fungible Token Metadata as per official NEP-148 standard (https://github.com/near/NEPs/blob/master/neps/nep-0148.md). 27 | */ 28 | export interface FungibleTokenMetadata { 29 | /** A string. Should be ft-1.0.0 to indicate that a Fungible Token contract adheres to the current versions of this Metadata and the Fungible Token Core specs. This will allow consumers of the Fungible Token to know if they support the features of a given contract. */ 30 | spec: string; 31 | /** The human-readable name of the token. */ 32 | name: string; 33 | /** The abbreviation, like wETH or AMPL. */ 34 | symbol: string; 35 | /** Used in frontends to show the proper significant digits of a token. This concept is explained well in this OpenZeppelin post (https://docs.openzeppelin.com/contracts/3.x/erc20#a-note-on-decimals). */ 36 | decimals: number; 37 | /** 38 | * A small image associated with this token. Must be a data URL, to help consumers display it quickly while protecting user data. 39 | * Recommendation: use optimized SVG, which can result in high-resolution images with only 100s of bytes of storage cost. 40 | * (Note that these storage costs are incurred to the token owner/deployer, but that querying these icons is a very cheap & cacheable read operation for all consumers of the contract and the RPC nodes that serve the data.) 41 | * Recommendation: create icons that will work well with both light-mode and dark-mode websites by either using middle-tone color schemes, or by embedding media queries in the SVG. 42 | */ 43 | icon?: string; 44 | /** A link to a valid JSON file containing various keys offering supplementary details on the token. Example: /ipfs/QmdmQXB2mzChmMeKY47C43LxUdg1NDJ5MWcKMKxDu7RgQm, https://example.com/token.json, etc. If the information given in this document conflicts with the on-chain attributes, the values in reference shall be considered the source of truth. */ 45 | reference?: string; 46 | /** The base64-encoded sha256 hash of the JSON file contained in the reference field. This is to guard against off-chain tampering. */ 47 | reference_hash?: string; 48 | } 49 | -------------------------------------------------------------------------------- /packages/core/src/lib/types/params.ts: -------------------------------------------------------------------------------- 1 | //import { Account } from "near-api-js"; 2 | import { Maybe } from "../keypom"; 3 | import { PasswordPerUse } from "./drops"; 4 | import { GeneratedKeyPairs } from "./general"; 5 | import { 6 | ProtocolReturnedDropConfig, 7 | ProtocolReturnedFCData, 8 | ProtocolReturnedFTData, 9 | ProtocolReturnedNFTData, 10 | ProtocolReturnedSimpleData, 11 | } from "./protocol"; 12 | import { Account } from "@near-js/accounts"; 13 | import { Transaction } from "@near-js/transactions"; 14 | import { BrowserWalletBehaviour } from "@near-wallet-selector/core"; 15 | import { Wallet } from "@near-wallet-selector/core"; 16 | 17 | export type AnyWallet = BrowserWalletBehaviour | Wallet | Promise; 18 | 19 | /** 20 | * Information returned when creating a drop or adding keys via `createDrop` and `addKeys` respectively. 21 | */ 22 | export interface CreateOrAddReturn { 23 | /** The responses to any transactions that were signed and sent to the network. */ 24 | responses?: any; 25 | /** Information about the transactions if `returnTransactions` is specified in the arguments. This will result in the information being returned instead of signed and sent. */ 26 | transactions?: Transaction[]; 27 | /** The required deposit that should be attached to the transaction. */ 28 | requiredDeposit?: string; 29 | /** Any keys that were automatically generated. */ 30 | keys?: GeneratedKeyPairs; 31 | /** The drop ID for the drop that is being interacted with. */ 32 | dropId: string; 33 | } 34 | 35 | /** 36 | * @ignore 37 | */ 38 | export interface RegisterUsesParams { 39 | account?: Account; 40 | wallet?: AnyWallet; 41 | dropId: string; 42 | numUses: number; 43 | useBalance?: boolean; 44 | } 45 | 46 | /** @internal */ 47 | export interface CreateDropProtocolArgs { 48 | public_keys?: string[]; 49 | deposit_per_use: string; 50 | 51 | drop_id?: string; 52 | config?: ProtocolReturnedDropConfig; 53 | metadata?: string; 54 | required_gas?: string; 55 | simple?: ProtocolReturnedSimpleData; 56 | ft?: ProtocolReturnedFTData; 57 | nft?: ProtocolReturnedNFTData; 58 | fc?: ProtocolReturnedFCData; 59 | passwords_per_use?: Array>>; 60 | } 61 | -------------------------------------------------------------------------------- /packages/core/src/lib/types/simple.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Specific configurable information for Simple drops. 3 | */ 4 | export interface SimpleData { 5 | /** If this is set to true, keys can be created and registered AFTER they've been created (for simple and FC drops only). */ 6 | lazyRegister?: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/test/ext-wasm/main.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keypom/keypom-js/a422762d00f843fefd4e5f46bba180ae69c376ea/packages/core/test/ext-wasm/main.wasm -------------------------------------------------------------------------------- /packages/core/test/instant-sign-in.ts: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const homedir = require("os").homedir(); 3 | const { readFileSync } = require("fs"); 4 | const { UnencryptedFileSystemKeyStore } = require("@near-js/keystores-node"); 5 | const { Account } = require("@near-js/accounts"); 6 | const { connect, Near } = require("@near-js/wallet-account"); 7 | const { 8 | initKeypom, 9 | createTrialAccountDrop, 10 | generateKeys, 11 | claimTrialAccountDrop, 12 | getEnv, 13 | } = require("../lib"); 14 | const { parseNearAmount } = require("@near-js/utils"); 15 | 16 | const accountId = "benjiman.testnet"; 17 | const NETWORK_ID = "testnet"; 18 | const instances = { 19 | keypom: { 20 | url: "http://localhost:3000/#instant-url/ACCOUNT_ID/SECRET_KEY/MODULE_ID", 21 | moduleId: "sweat-wallet", 22 | contract: "1714778045977-marketplace.testnet", 23 | allowance: parseNearAmount("2"), 24 | numLinks: 1, 25 | }, 26 | guestBook: { 27 | url: "http://localhost:5173/#instant-url/ACCOUNT_ID/SECRET_KEY/MODULE_ID", 28 | moduleId: "sweat-wallet", 29 | contract: "guestbook.near-examples.testnet", 30 | allowance: parseNearAmount("2"), 31 | numLinks: 1, 32 | }, 33 | }; 34 | 35 | async function createInstantSignIn() { 36 | // Initiate connection to the NEAR blockchain. 37 | const CREDENTIALS_DIR = ".near-credentials"; 38 | const credentialsPath = path.join(homedir, CREDENTIALS_DIR); 39 | 40 | let keyStore = new UnencryptedFileSystemKeyStore(credentialsPath); 41 | 42 | let nearConfig = { 43 | networkId: NETWORK_ID, 44 | keyStore: keyStore, 45 | nodeUrl: `https://rpc.${NETWORK_ID}.near.org`, 46 | walletUrl: `https://wallet.${NETWORK_ID}.near.org`, 47 | helperUrl: `https://helper.${NETWORK_ID}.near.org`, 48 | explorerUrl: `https://explorer.${NETWORK_ID}.near.org`, 49 | }; 50 | 51 | let near = new Near(nearConfig); 52 | const accountObj = new Account(near.connection, accountId); 53 | 54 | // Initialize the SDK and point it to the custom NEAR object that was created. 55 | await initKeypom({ 56 | near, 57 | network: NETWORK_ID, 58 | }); 59 | 60 | // Loop through each key in the instances object and get the value's numLinks property 61 | for (const [key, value] of Object.entries(instances)) { 62 | console.log(`\n\n`); 63 | 64 | let numKeys = value.numLinks; 65 | const { secretKeys, publicKeys } = await generateKeys({ numKeys }); 66 | console.log(`Created ${secretKeys.length} keys for ${key}`); 67 | console.log(`Public Keys: ${publicKeys}`); 68 | console.log(`Private Keys: ${secretKeys}`); 69 | 70 | for (const publicKey of publicKeys) { 71 | await accountObj.addKey( 72 | publicKey, 73 | value.contract, 74 | "", 75 | value.allowance 76 | ); 77 | } 78 | 79 | let returnedURLs = []; 80 | // loop through all secret keys 81 | secretKeys.forEach((secretKey) => { 82 | // insert the secret key into the base URL 83 | let url = value.url.replace("SECRET_KEY", secretKey); 84 | url = url.replace("ACCOUNT_ID", accountId); 85 | url = url.replace("MODULE_ID", value.moduleId); 86 | 87 | // add the URL to the array of URLs 88 | returnedURLs.push(url); 89 | }); 90 | 91 | console.log(`${key}:`); 92 | console.log(returnedURLs.join("\n")); 93 | } 94 | 95 | console.log(`\n\n`); 96 | } 97 | 98 | createInstantSignIn(); 99 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.node.json", 3 | "compilerOptions": { 4 | "preserveSymlinks": false, 5 | "outDir": "./lib", 6 | "baseUrl": ".", // Make sure baseUrl is set 7 | "paths": { 8 | "@near-js/types/*": ["node_modules/@near-js/types/lib/*"], 9 | "@near-js/types/src/provider/protocol": [ 10 | "node_modules/@near-js/types/lib/provider/protocol" 11 | ] 12 | } 13 | }, 14 | "files": ["src/index.ts"], 15 | "types": ["node"] 16 | } 17 | -------------------------------------------------------------------------------- /packages/core/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "entryPoints": ["./src/index.ts"], 4 | "out": "docs" 5 | } -------------------------------------------------------------------------------- /packages/fastauth/data/clientLog.json: -------------------------------------------------------------------------------- 1 | "" -------------------------------------------------------------------------------- /packages/fastauth/data/signatures.json: -------------------------------------------------------------------------------- 1 | { 2 | "signatures": [ 3 | { 4 | "big_r": { 5 | "affine_point": "022EF2BB384895A50397E35CFF82BC5119A7E660264E406290F6F46D61A3E14B16" 6 | }, 7 | "s": { 8 | "scalar": "18E21C933D2979C01823289D88F13E8D4CFCA19D4094070FDD103130E0F77670" 9 | }, 10 | "recovery_id": 1 11 | } 12 | ], 13 | "txnDatas": [ 14 | { 15 | "nonce": "178042356000001", 16 | "blockHash": "3gZeXQ2w3hLLm2zYCFGAJD9B7UqsEDjs1bB3SoKgPjRM" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /packages/fastauth/data/trialData.json: -------------------------------------------------------------------------------- 1 | { 2 | "trialId": 20, 3 | "trialContractId": "1729530318593-trial-contract.testnet", 4 | "trialKeys": [ 5 | { 6 | "derivationPath": "ed25519:2k1tAe5W9M4f1pr6RJ1LJAsXAcYruXCyMK2LNtHJhAKg", 7 | "trialAccountSecretKey": "ed25519:3uRPfK5YWAnmGP15dT9aZWmkEQwkaN7u3eqb4PZvhuBdmUKxtADoBK9DzYMFryus9r5GJZfpqPaeM88PZvKcG9T4", 8 | "trialAccountPublicKey": "ed25519:2k1tAe5W9M4f1pr6RJ1LJAsXAcYruXCyMK2LNtHJhAKg", 9 | "mpcKey": "secp256k1:3XUjKVSqVvuTKkiZS3xzHEaot7gqM9YeqmGEgQoppt6QNt4gBKm2EfHDEquAW3StQMJgPrJ7wokYY9Pzjeg7zLmR" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /packages/fastauth/deploy/abis/baseGuestbook.ts: -------------------------------------------------------------------------------- 1 | export const BASE_GUESTBOOK_ABI = [ 2 | "function setMessage(string _message)", 3 | "function getMessage() view returns (string)", 4 | ]; 5 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/abis/baseNFT.ts: -------------------------------------------------------------------------------- 1 | export const BASE_NFT_ABI = [ 2 | "function lazyMint(address to, uint256 series, uint256 quantity, bytes data)", 3 | "function batchLazyMint(address to, uint256[] seriesIds, uint256[] amounts, bytes data)", 4 | "function multiAddressLazyMint(address[] addresses, uint256[] seriesIds, bytes data)", 5 | "function multiAddressLazyMintTest(uint256[] bar)", 6 | "function approveCreator(address creator)", 7 | "function revokeCreator(address creator)", 8 | "function setBaseURI(string baseURI)", 9 | "function initializeSeries(uint256 maxSupply, string token_uri)", 10 | ]; 11 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/broadcastSig.ts: -------------------------------------------------------------------------------- 1 | // src/main.ts 2 | 3 | import { MPCSignature, TrialAccountManager } from "../src/index"; 4 | import { readFromFile, writeToFile } from "./utils/fileOps"; 5 | import path from "path"; 6 | import fs from "fs"; 7 | import { logError, logInfo, logSuccess } from "./utils/logUtils"; 8 | import { isFinalExecutionOutcome } from "./utils/nearUtils"; 9 | import { TransactionResponse } from "ethers"; 10 | import { config as loadEnv } from "dotenv"; 11 | import { TransactionData } from "../src/lib/performAction"; 12 | import { NetworkId } from "@near-wallet-selector/core"; 13 | 14 | // Load environment variables from .env file 15 | loadEnv(); 16 | 17 | async function main() { 18 | // Parse config name from command line arguments 19 | const args = process.argv.slice(2); 20 | if (args.length === 0) { 21 | logError("Please provide a config name."); 22 | process.exit(1); 23 | } 24 | const configName = args[0]; 25 | logInfo(`Using config: ${configName}`); 26 | 27 | // Load the appropriate config 28 | const configPath = path.join(__dirname, "configs", `${configName}.ts`); 29 | if (!fs.existsSync(configPath)) { 30 | logError(`Config file not found: ${configPath}`); 31 | process.exit(1); 32 | } 33 | const { config, actionsToPerform } = await import( 34 | `./configs/${configName}` 35 | ); 36 | 37 | // Create TrialAccountManager instance 38 | const trialManager = new TrialAccountManager({ 39 | trialContractId: config.trialContractId, 40 | mpcContractId: config.mpcContractId, 41 | networkId: config.networkId as NetworkId, 42 | maxRetries: 5, 43 | initialDelayMs: 2000, 44 | backoffFactor: 2, 45 | }); 46 | 47 | // read the signatures from the file 48 | const { trialId, trialKeys } = readFromFile( 49 | config.dataDir, 50 | "trialData.json" 51 | ); 52 | const { 53 | signatures, 54 | txnDatas, 55 | }: { signatures: MPCSignature[]; txnDatas: TransactionData[] } = 56 | readFromFile(config.dataDir, "signatures.json"); 57 | 58 | let results: Array = []; 59 | for (const trialKey of trialKeys) { 60 | const trialAccountSecretKey = trialKey.trialAccountSecretKey; 61 | 62 | let iter = 0; 63 | for (const action of actionsToPerform) { 64 | const providerUrl = `https://base-sepolia.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`; 65 | 66 | const { result, clientLog } = 67 | await trialManager.broadcastTransaction({ 68 | trialAccountSecretKey, 69 | actionToPerform: action, 70 | providerUrl, 71 | signatureResult: signatures[0], 72 | txnData: txnDatas[iter++], 73 | }); 74 | 75 | writeToFile(clientLog, config.dataDir, "clientLog.json"); 76 | results.push(result); 77 | logSuccess(`Actions performed successfully.`); 78 | } 79 | 80 | logSuccess( 81 | `${actionsToPerform.length} Action(s) performed successfully.` 82 | ); 83 | 84 | for (const result of results) { 85 | if (isFinalExecutionOutcome(result)) { 86 | console.log( 87 | // @ts-ignore 88 | `https://testnet.nearblocks.io/txns/${result.transaction.hash}#execution` 89 | ); 90 | } else { 91 | console.log(`https://sepolia.basescan.org/tx/${result}`); 92 | } 93 | } 94 | } 95 | 96 | // Prepare trial data to write to file 97 | const trialDataToWrite = { 98 | trialId, 99 | trialContractId: config.trialContractId, 100 | trialKeys, 101 | }; 102 | 103 | // Write trial data to a file 104 | writeToFile(trialDataToWrite, config.dataDir, "trialData.json"); 105 | logSuccess("Trial data written to file."); 106 | } 107 | 108 | main().catch((error) => { 109 | logError("Error in deploy: " + error); 110 | }); 111 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/compareLogs.ts: -------------------------------------------------------------------------------- 1 | import { readFromFile } from "./utils/fileOps"; 2 | import { compareAndLog } from "./utils/logUtils"; 3 | 4 | /** 5 | * Compares contract logs with client logs and logs the results. 6 | */ 7 | function compareLogs() { 8 | console.log("Starting log comparison...\n"); 9 | const dataDir = "./data"; 10 | 11 | // Read the contract logs 12 | const contractLog = readFromFile(dataDir, "contractLogs.json"); 13 | 14 | // Read the client logs 15 | const clientLog = readFromFile(dataDir, "clientLog.json"); 16 | 17 | console.log("Comparing Chain ID..."); 18 | compareAndLog( 19 | "Chain ID", 20 | contractLog["Chain ID"].toString(), 21 | clientLog["Chain ID"].toString() 22 | ); 23 | 24 | console.log("\nComparing Nonce..."); 25 | compareAndLog( 26 | "Nonce", 27 | contractLog["Nonce"].toString(), 28 | clientLog["Nonce"].toString() 29 | ); 30 | 31 | console.log("\nComparing Max Priority Fee Per Gas..."); 32 | compareAndLog( 33 | "Max Priority Fee Per Gas", 34 | contractLog["Max Priority Fee Per Gas"], 35 | clientLog["Max Priority Fee Per Gas"] 36 | ); 37 | 38 | console.log("\nComparing Max Fee Per Gas..."); 39 | compareAndLog( 40 | "Max Fee Per Gas", 41 | contractLog["Max Fee Per Gas"], 42 | clientLog["Max Fee Per Gas"] 43 | ); 44 | 45 | console.log("\nComparing Gas Limit..."); 46 | compareAndLog( 47 | "Gas Limit", 48 | contractLog["Gas Limit"], 49 | clientLog["Gas Limit"] 50 | ); 51 | 52 | console.log("\nComparing Contract Address..."); 53 | compareAndLog( 54 | "Contract Address", 55 | contractLog["Contract Address"], 56 | clientLog["Contract Address"], 57 | (value) => { 58 | // Convert byte array to hex string if necessary 59 | if (Array.isArray(value)) { 60 | return "0x" + Buffer.from(value).toString("hex"); 61 | } 62 | return value.toLowerCase(); 63 | } 64 | ); 65 | 66 | console.log("\nComparing Value..."); 67 | compareAndLog("Value", contractLog["Value"], clientLog["Value"]); 68 | 69 | console.log("\nComparing Input Data..."); 70 | compareAndLog( 71 | "Input Data", 72 | contractLog["Input Data"], 73 | clientLog["Input Data"] 74 | ); 75 | 76 | console.log("\nComparing Hashed Payload..."); 77 | compareAndLog( 78 | "Hashed Payload", 79 | contractLog["Hashed Payload"], 80 | clientLog["Hashed Payload"] 81 | ); 82 | 83 | console.log("\nLog comparison complete."); 84 | } 85 | 86 | // Run the comparison 87 | compareLogs(); 88 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/configs/evmSimple.ts: -------------------------------------------------------------------------------- 1 | // src/configs/evmSimple.ts 2 | 3 | import path from "path"; 4 | import os from "os"; 5 | import { Config } from "./type"; 6 | import { TrialData, ActionToPerform, AccessList } from "../../src/index"; 7 | import { BASE_GUESTBOOK_ABI } from "../abis/baseGuestbook"; 8 | import { parseEther } from "ethers"; 9 | import { UnencryptedFileSystemKeyStore } from "near-api-js/lib/key_stores"; 10 | 11 | const homedir = os.homedir(); 12 | const CREDENTIALS_DIR = ".near-credentials"; 13 | const credentialsPath = path.join(homedir, CREDENTIALS_DIR); 14 | 15 | export const config: Config = { 16 | networkId: "testnet", 17 | trialContractId: "1729530318593-trial-contract.testnet", 18 | signerAccountId: "benjiman.testnet", 19 | keyStore: new UnencryptedFileSystemKeyStore(credentialsPath), 20 | mpcContractId: "v1.signer-prod.testnet", 21 | numberOfKeys: 1, 22 | dataDir: "./data", 23 | }; 24 | 25 | export const trialData: TrialData = { 26 | constraintsByChainId: { 27 | EVM: { 28 | chainId: 421614, 29 | allowedMethods: ["increment"], 30 | allowedContracts: ["0x6d21161d1D17cDCA58707829E4d57D5a4EfE5489"], 31 | maxGas: 1000000, // Optional 32 | maxValue: "0", // Optional 33 | initialDeposit: parseEther("0.004"), // roughly 15$ 34 | }, 35 | }, 36 | usageConstraints: null, 37 | interactionLimits: null, 38 | exitConditions: null, 39 | expirationTime: null, 40 | }; 41 | 42 | // ARGUMENTS TO THE FUNCTION CALL 43 | const _message = "Hello from the MPC Trial Account EVM Config!"; 44 | const args = [_message]; 45 | 46 | const accessList: AccessList = []; 47 | export const actionsToPerform: ActionToPerform[] = [ 48 | { 49 | chain: "EVM", 50 | chainId: 421614, 51 | targetContractId: "0xdf5c3bd628a11C97BB25d441D8b6d9Ce974dc552", 52 | methodName: "setMessage", 53 | args, 54 | abi: BASE_GUESTBOOK_ABI, // Provide the ABI of the contract 55 | value: "0", // If no ETH is sent along with the transaction 56 | accessList: accessList, 57 | }, 58 | ]; 59 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/configs/nearSimple.ts: -------------------------------------------------------------------------------- 1 | // src/configs/simple.ts 2 | 3 | import { UnencryptedFileSystemKeyStore } from "near-api-js/lib/key_stores"; 4 | import path from "path"; 5 | import os from "os"; 6 | import { Config } from "./type"; 7 | import { TrialData, ActionToPerform } from "../../src/index"; 8 | import { parseNearAmount } from "near-api-js/lib/utils/format"; 9 | 10 | const homedir = os.homedir(); 11 | const CREDENTIALS_DIR = ".near-credentials"; 12 | const credentialsPath = path.join(homedir, CREDENTIALS_DIR); 13 | 14 | export const config: Config = { 15 | networkId: "testnet", 16 | trialContractId: "1729530318593-trial-contract.testnet", 17 | signerAccountId: "benjiman.testnet", 18 | keyStore: new UnencryptedFileSystemKeyStore(credentialsPath), 19 | mpcContractId: "v1.signer-prod.testnet", 20 | numberOfKeys: 1, 21 | dataDir: "./data", 22 | }; 23 | 24 | export const trialData: TrialData = { 25 | constraintsByChainId: { 26 | NEAR: { 27 | allowedMethods: ["add_message"], 28 | allowedContracts: ["guestbook.near-examples.testnet"], 29 | maxGas: null, 30 | maxDeposit: null, 31 | initialDeposit: parseNearAmount("10")!, 32 | }, 33 | }, 34 | usageConstraints: null, 35 | interactionLimits: null, 36 | exitConditions: null, 37 | expirationTime: null, 38 | }; 39 | 40 | export const actionsToPerform: ActionToPerform[] = [ 41 | { 42 | chain: "NEAR", 43 | targetContractId: "guestbook.near-examples.testnet", 44 | methodName: "add_message", 45 | args: { text: "Hello from the MPC Trial Account Near Config!" }, 46 | attachedDepositNear: "1", 47 | gas: "300000000000000", 48 | }, 49 | ]; 50 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/configs/omniChainSimple.ts: -------------------------------------------------------------------------------- 1 | // src/configs/onniChainSimple.ts 2 | 3 | import path from "path"; 4 | import os from "os"; 5 | import { Config } from "./type"; 6 | import { TrialData, ActionToPerform, AccessList } from "../../src/index"; 7 | import { BASE_GUESTBOOK_ABI } from "../abis/baseGuestbook"; 8 | import { parseEther } from "ethers"; 9 | import { UnencryptedFileSystemKeyStore } from "near-api-js/lib/key_stores"; 10 | import { parseNearAmount } from "near-api-js/lib/utils/format"; 11 | 12 | const homedir = os.homedir(); 13 | const CREDENTIALS_DIR = ".near-credentials"; 14 | const credentialsPath = path.join(homedir, CREDENTIALS_DIR); 15 | 16 | export const config: Config = { 17 | networkId: "testnet", 18 | trialContractId: "1729530318593-trial-contract.testnet", 19 | signerAccountId: "benjiman.testnet", 20 | keyStore: new UnencryptedFileSystemKeyStore(credentialsPath), 21 | mpcContractId: "v1.signer-prod.testnet", 22 | numberOfKeys: 1, 23 | dataDir: "./data", 24 | }; 25 | 26 | export const trialData: TrialData = { 27 | constraintsByChainId: { 28 | EVM: { 29 | chainId: 421614, 30 | allowedMethods: ["increment"], 31 | allowedContracts: ["0x6d21161d1D17cDCA58707829E4d57D5a4EfE5489"], 32 | maxGas: 1000000, // Optional 33 | maxValue: "0", // Optional 34 | initialDeposit: parseEther("0.004"), // roughly 15$ 35 | }, 36 | NEAR: { 37 | allowedMethods: ["add_message"], 38 | allowedContracts: ["guestbook.near-examples.testnet"], 39 | maxGas: null, 40 | maxDeposit: null, 41 | initialDeposit: parseNearAmount("10")!, 42 | }, 43 | }, 44 | usageConstraints: null, 45 | interactionLimits: null, 46 | exitConditions: null, 47 | expirationTime: null, 48 | }; 49 | 50 | // ARGUMENTS TO THE FUNCTION CALL 51 | const _message = "Hello from the MPC Trial Account EVM Config!"; 52 | const evmArgs = [_message]; 53 | 54 | const accessList: AccessList = []; 55 | export const actionsToPerform: ActionToPerform[] = [ 56 | { 57 | chain: "NEAR", 58 | targetContractId: "guestbook.near-examples.testnet", 59 | methodName: "add_message", 60 | args: { text: "Hello from the MPC Trial Account Near Config!" }, 61 | attachedDepositNear: "1", 62 | gas: "300000000000000", 63 | }, 64 | { 65 | chain: "EVM", 66 | chainId: 421614, 67 | targetContractId: "0xdf5c3bd628a11C97BB25d441D8b6d9Ce974dc552", 68 | methodName: "setMessage", 69 | args: evmArgs, 70 | abi: BASE_GUESTBOOK_ABI, // Provide the ABI of the contract 71 | value: "0", // If no ETH is sent along with the transaction 72 | accessList: accessList, 73 | }, 74 | ]; 75 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/configs/type.ts: -------------------------------------------------------------------------------- 1 | import { UnencryptedFileSystemKeyStore } from "@near-js/keystores-node"; 2 | 3 | /** 4 | * Configuration required to initialize the NEAR connection and other parameters. 5 | */ 6 | export interface Config { 7 | trialContractId: string; 8 | networkId: string; 9 | signerAccountId: string; 10 | keyStore: UnencryptedFileSystemKeyStore; 11 | mpcContractId: string; 12 | numberOfKeys: number; 13 | dataDir: string; 14 | } 15 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/utils/evmUtils.ts: -------------------------------------------------------------------------------- 1 | import { ethers, JsonRpcProvider } from "ethers"; 2 | 3 | export function getSponsorEVMWallet( 4 | evmPrivateKey: string, 5 | providerUrl: string, 6 | chainId: string 7 | ) { 8 | // Convert the hex private key string into a Uint8Array 9 | const hexPrivateKey = evmPrivateKey.startsWith("0x") 10 | ? evmPrivateKey.slice(2) 11 | : evmPrivateKey; 12 | 13 | const privateKeyBytes = Uint8Array.from(Buffer.from(hexPrivateKey, "hex")); 14 | 15 | // Initialize provider 16 | const provider = new JsonRpcProvider(providerUrl, parseInt(chainId, 10)); 17 | 18 | // Create the wallet using the private key bytes 19 | const SPONSOR_WALLET = new ethers.Wallet( 20 | new ethers.SigningKey(privateKeyBytes), 21 | provider 22 | ); 23 | 24 | return SPONSOR_WALLET; 25 | } 26 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/utils/fileOps.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | 4 | /** 5 | * Ensures that a directory exists; if not, it creates the directory. 6 | * 7 | * @param dirPath - The path to the directory. 8 | */ 9 | function ensureDirExists(dirPath: string): void { 10 | if (!fs.existsSync(dirPath)) { 11 | fs.mkdirSync(dirPath, { recursive: true }); 12 | } 13 | } 14 | 15 | /** 16 | * Writes an object to a JSON file. 17 | * 18 | * @param filePath - The path to the JSON file. 19 | * @param data - The data to write to the file. 20 | */ 21 | function writeJSONFile(filePath: string, data: any): void { 22 | fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); 23 | } 24 | 25 | /** 26 | * Writes an object to a JSON file. 27 | * @param filePath - The path to the JSON file. 28 | * @param data - The data to write to the file. 29 | * @throws If the file cannot be written. 30 | * @throws If the file contains invalid JSON. 31 | */ 32 | export function writeToFile( 33 | data: any, 34 | dataDir: string, 35 | fileName: string, 36 | ): void { 37 | // Ensure the data directory exists 38 | ensureDirExists(dataDir); 39 | 40 | // Save the trial keys to a file 41 | const filePath = path.join(dataDir, fileName); 42 | writeJSONFile(filePath, data); 43 | } 44 | 45 | /** 46 | * Reads an object from a JSON file. 47 | * @param filePath - The path to the JSON file. 48 | * @returns The object read from the file. 49 | * @throws If the file does not exist or cannot be read. 50 | * @throws If the file contains invalid JSON. 51 | */ 52 | export function readFromFile(dataDir: string, fileName: string): any { 53 | const filePath = path.join(dataDir, fileName); 54 | return JSON.parse(fs.readFileSync(filePath, "utf-8")); 55 | } 56 | -------------------------------------------------------------------------------- /packages/fastauth/deploy/utils/nearUtils.ts: -------------------------------------------------------------------------------- 1 | import { FinalExecutionOutcome } from "@near-wallet-selector/core"; 2 | import { Near } from "near-api-js"; 3 | import { Config } from "../configs/type"; 4 | 5 | /** 6 | * Initializes a NEAR connection using the provided configuration. 7 | * 8 | * @param config - The configuration object containing network ID, key store, etc. 9 | * @returns A Promise that resolves to a Near instance. 10 | */ 11 | export async function initNear(config: Config): Promise { 12 | const nearConfig = { 13 | networkId: config.networkId, 14 | nodeUrl: `https://rpc.${config.networkId}.near.org`, 15 | keyStore: config.keyStore, 16 | }; 17 | const near = new Near(nearConfig); 18 | return near; 19 | } 20 | 21 | export function isFinalExecutionOutcome( 22 | result: any 23 | ): result is FinalExecutionOutcome { 24 | return ( 25 | result && 26 | typeof result === "object" && 27 | "final_execution_status" in result && 28 | "status" in result && 29 | "transaction" in result && 30 | "transaction_outcome" in result && 31 | "receipts_outcome" in result 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /packages/fastauth/lib/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Main entry point for the Trial Accounts package. 3 | * 4 | * This package provides functions to deploy trial contracts, 5 | * create trials, add trial accounts, activate trial accounts, 6 | * perform actions, and broadcast transactions. 7 | * 8 | * @packageDocumentation 9 | */ 10 | export { setupWalletSelector } from "./lib/setupWalletSelector"; 11 | export { setupModal } from "./lib/modal"; 12 | -------------------------------------------------------------------------------- /packages/fastauth/lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // index.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | exports.setupModal = exports.setupWalletSelector = void 0; 5 | /** 6 | * Main entry point for the Trial Accounts package. 7 | * 8 | * This package provides functions to deploy trial contracts, 9 | * create trials, add trial accounts, activate trial accounts, 10 | * perform actions, and broadcast transactions. 11 | * 12 | * @packageDocumentation 13 | */ 14 | // index.ts 15 | var setupWalletSelector_1 = require("./lib/setupWalletSelector"); 16 | Object.defineProperty(exports, "setupWalletSelector", { enumerable: true, get: function () { return setupWalletSelector_1.setupWalletSelector; } }); 17 | var modal_1 = require("./lib/modal"); 18 | Object.defineProperty(exports, "setupModal", { enumerable: true, get: function () { return modal_1.setupModal; } }); 19 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/FastAuthModal.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { WalletSelector } from "@near-wallet-selector/core"; 3 | import { FastAuthModalOptions } from "./modal"; 4 | interface FastAuthModalProps { 5 | selector: WalletSelector; 6 | options: FastAuthModalOptions; 7 | isVisible: boolean; 8 | onClose: () => void; 9 | walletSelectorModal: any; 10 | } 11 | declare const FastAuthModal: React.FC; 12 | export default FastAuthModal; 13 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/FastAuthWallet.d.ts: -------------------------------------------------------------------------------- 1 | declare const FastAuthWallet: any; 2 | export default FastAuthWallet; 3 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare const ENV_VARIABLES: { 2 | local: { 3 | MPC_CONTRACT_ID: string; 4 | FASTAUTH_CONTRACT_ID: string; 5 | STORAGE_KEY: string; 6 | WORKER_BASE_URL: string; 7 | }; 8 | testnet: { 9 | MPC_CONTRACT_ID: string; 10 | FASTAUTH_CONTRACT_ID: string; 11 | STORAGE_KEY: string; 12 | WORKER_BASE_URL: string; 13 | }; 14 | }; 15 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/constants.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.ENV_VARIABLES = void 0; 4 | exports.ENV_VARIABLES = { 5 | local: { 6 | MPC_CONTRACT_ID: "v1.signer-prod.testnet", 7 | FASTAUTH_CONTRACT_ID: "1732654372972-fastauth.testnet", 8 | STORAGE_KEY: "FAST_AUTH_WALLET_STATE", 9 | WORKER_BASE_URL: "http://localhost:8787", 10 | }, 11 | testnet: { 12 | MPC_CONTRACT_ID: "v1.signer-prod.testnet", 13 | FASTAUTH_CONTRACT_ID: "1732654372972-fastauth.testnet", 14 | STORAGE_KEY: "FAST_AUTH_WALLET_STATE", 15 | WORKER_BASE_URL: "https://fastauth-worker-development.keypom.workers.dev", 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/AppleIcon.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | declare const AppleIcon: React.FC; 3 | export default AppleIcon; 4 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/AppleIcon.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const jsx_runtime_1 = require("react/jsx-runtime"); 7 | const react_1 = __importDefault(require("react")); 8 | const AppleIcon = () => ((0, jsx_runtime_1.jsx)("svg", { width: "24", height: "24", viewBox: "0 0 17 48", xmlns: "http://www.w3.org/2000/svg", preserveAspectRatio: "xMidYMid meet" // Ensures the aspect ratio is preserved 9 | , children: (0, jsx_runtime_1.jsx)("path", { d: "m15.5752 19.0792a4.2055 4.2055 0 0 0 -2.01 3.5376 4.0931 4.0931 0 0 0 2.4908 3.7542 9.7779 9.7779 0 0 1 -1.2755 2.6351c-.7941 1.1431-1.6244 2.2862-2.8878 2.2862s-1.5883-.734-3.0443-.734c-1.42 0-1.9252.7581-3.08.7581s-1.9611-1.0589-2.8876-2.3584a11.3987 11.3987 0 0 1 -1.9373-6.1487c0-3.61 2.3464-5.523 4.6566-5.523 1.2274 0 2.25.8062 3.02.8062.734 0 1.8771-.8543 3.2729-.8543a4.3778 4.3778 0 0 1 3.6822 1.841zm-6.8586-2.0456a1.3865 1.3865 0 0 1 -.2527-.024 1.6557 1.6557 0 0 1 -.0361-.337 4.0341 4.0341 0 0 1 1.0228-2.5148 4.1571 4.1571 0 0 1 2.7314-1.4078 1.7815 1.7815 0 0 1 .0361.373 4.1487 4.1487 0 0 1 -.9867 2.587 3.6039 3.6039 0 0 1 -2.5148 1.3236z" }) })); 10 | exports.default = AppleIcon; 11 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/CloseIcon.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | export declare const CloseIcon: React.FC; 3 | export default CloseIcon; 4 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/CloseIcon.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.CloseIcon = void 0; 7 | const jsx_runtime_1 = require("react/jsx-runtime"); 8 | // lib/icons/CloseIcon.tsx 9 | const react_1 = __importDefault(require("react")); 10 | const CloseIcon = () => ((0, jsx_runtime_1.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [(0, jsx_runtime_1.jsx)("path", { d: "M11 3L3 11", stroke: "var(--fastauth-close-button-icon-color)", strokeWidth: "2", strokeLinecap: "round" }), (0, jsx_runtime_1.jsx)("path", { d: "M3 3L11 11", stroke: "var(--fastauth-close-button-icon-color)", strokeWidth: "2", strokeLinecap: "round" })] })); 11 | exports.CloseIcon = CloseIcon; 12 | exports.default = exports.CloseIcon; 13 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/DiscordIcon.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | declare const DiscordIcon: React.FC; 3 | export default DiscordIcon; 4 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/DiscordIcon.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const jsx_runtime_1 = require("react/jsx-runtime"); 7 | const react_1 = __importDefault(require("react")); 8 | const DiscordIcon = () => ((0, jsx_runtime_1.jsx)("img", { src: "https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/636e0a69f118df70ad7828d4_icon_clyde_blurple_RGB.svg", alt: "Discord Icon", style: { width: "24px", height: "24px", objectFit: "contain" } })); 9 | exports.default = DiscordIcon; 10 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/GoogleIcon.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | declare const GoogleIcon: React.FC; 3 | export default GoogleIcon; 4 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/GoogleIcon.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const jsx_runtime_1 = require("react/jsx-runtime"); 7 | // src/icons/GoogleIcon.tsx 8 | const react_1 = __importDefault(require("react")); 9 | const GoogleIcon = () => ((0, jsx_runtime_1.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 48 48", style: { width: "24px", height: "24px" }, "aria-label": "Google Icon", role: "img", children: [(0, jsx_runtime_1.jsx)("path", { fill: "#fbc02d", d: "M43.611,20.083H42V20H24v8h11.303c-1.649,4.657-6.08,8-11.303,8c-6.627,0-12-5.373-12-12\ts5.373-12,12-12c3.059,0,5.842,1.154,7.961,3.039l5.657-5.657C34.046,6.053,29.268,4,24,4C12.955,4,4,12.955,4,24s8.955,20,20,20\ts20-8.955,20-20C44,22.659,43.862,21.35,43.611,20.083z" }), (0, jsx_runtime_1.jsx)("path", { fill: "#e53935", d: "M6.306,14.691l6.571,4.819C14.655,15.108,18.961,12,24,12c3.059,0,5.842,1.154,7.961,3.039\tl5.657-5.657C34.046,6.053,29.268,4,24,4C16.318,4,9.656,8.337,6.306,14.691z" }), (0, jsx_runtime_1.jsx)("path", { fill: "#4caf50", d: "M24,44c5.166,0,9.86-1.977,13.409-5.192l-6.19-5.238C29.211,35.091,26.715,36,24,36\tc-5.202,0-9.619-3.317-11.283-7.946l-6.522,5.025C9.505,39.556,16.227,44,24,44z" }), (0, jsx_runtime_1.jsx)("path", { fill: "#1565c0", d: "M43.611,20.083L43.595,20L42,20H24v8h11.303c-0.792,2.237-2.231,4.166-4.087,5.571\tc0.001-0.001,0.002-0.001,0.003-0.002l6.19,5.238C36.971,39.205,44,34,44,24C44,22.659,43.862,21.35,43.611,20.083z" })] })); 10 | exports.default = GoogleIcon; 11 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/WalletIcon.d.ts: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | declare const WalletIcon: React.FC; 3 | export default WalletIcon; 4 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/icons/WalletIcon.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const jsx_runtime_1 = require("react/jsx-runtime"); 7 | // src/icons/WalletIcon.tsx 8 | const react_1 = __importDefault(require("react")); 9 | const WalletIcon = () => ((0, jsx_runtime_1.jsxs)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [(0, jsx_runtime_1.jsx)("path", { d: "M21 7H3C1.9 7 1 7.9 1 9V15C1 16.1 1.9 17 3 17H21C22.1 17 23 16.1 23 15V9C23 7.9 22.1 7 21 7ZM21 15H3V9H21V15Z", fill: "currentColor" }), (0, jsx_runtime_1.jsx)("path", { d: "M7 11H17V13H7V11Z", fill: "currentColor" })] })); 10 | exports.default = WalletIcon; 11 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/modal.d.ts: -------------------------------------------------------------------------------- 1 | import { WalletSelector } from "@near-wallet-selector/core"; 2 | import { ModalOptions } from "@near-wallet-selector/modal-ui"; 3 | interface FastAuthModalProps { 4 | show: () => void; 5 | hide: () => void; 6 | } 7 | export interface FastAuthModalOptions extends ModalOptions { 8 | localTesting?: boolean; 9 | } 10 | export declare function setupModal(selector: WalletSelector, options: FastAuthModalOptions): FastAuthModalProps; 11 | export {}; 12 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/modal.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.setupModal = void 0; 7 | const jsx_runtime_1 = require("react/jsx-runtime"); 8 | const react_1 = __importDefault(require("react")); 9 | const client_1 = require("react-dom/client"); 10 | const FastAuthModal_1 = __importDefault(require("./FastAuthModal")); 11 | const modal_ui_1 = require("@near-wallet-selector/modal-ui"); // Import setupModal 12 | let root = null; 13 | function setupModal(selector, options) { 14 | let isVisible = false; 15 | let walletSelectorModal = null; 16 | const show = () => { 17 | isVisible = true; 18 | renderModal(); 19 | }; 20 | const hide = () => { 21 | isVisible = false; 22 | renderModal(); 23 | }; 24 | const renderModal = () => { 25 | const container = document.getElementById("fastauth-wallet-selector-modal") || 26 | document.createElement("div"); 27 | container.id = "fastauth-wallet-selector-modal"; 28 | document.body.appendChild(container); 29 | if (!root) { 30 | root = (0, client_1.createRoot)(container); 31 | } 32 | if (!walletSelectorModal) { 33 | walletSelectorModal = (0, modal_ui_1.setupModal)(selector, { 34 | contractId: options.contractId, 35 | methodNames: options.methodNames, 36 | theme: options.theme, 37 | description: options.description, 38 | // Include other options as needed 39 | }); 40 | } 41 | root.render((0, jsx_runtime_1.jsx)(FastAuthModal_1.default, { selector: selector, options: options, isVisible: isVisible, onClose: hide, walletSelectorModal: walletSelectorModal })); 42 | }; 43 | return { 44 | show, 45 | hide, 46 | }; 47 | } 48 | exports.setupModal = setupModal; 49 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/models/payload.d.ts: -------------------------------------------------------------------------------- 1 | export interface NearPayload { 2 | action: NearAction; 3 | nonce: string; 4 | } 5 | type NearAction = { 6 | FunctionCall: { 7 | contract_id: string; 8 | method_name: string; 9 | args: number[]; 10 | gas: string; 11 | deposit: string; 12 | }; 13 | } | { 14 | Transfer: { 15 | receiver_id: string; 16 | amount: string; 17 | }; 18 | }; 19 | export {}; 20 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/models/payload.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/setupWalletSelector.d.ts: -------------------------------------------------------------------------------- 1 | import { WalletSelectorParams } from "@near-wallet-selector/core"; 2 | interface FastAuthWalletParams extends WalletSelectorParams { 3 | localTesting?: boolean; 4 | } 5 | export declare const setupWalletSelector: (params: FastAuthWalletParams) => Promise; 6 | export {}; 7 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/setupWalletSelector.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // setupWalletSelector.ts 3 | var __importDefault = (this && this.__importDefault) || function (mod) { 4 | return (mod && mod.__esModule) ? mod : { "default": mod }; 5 | }; 6 | Object.defineProperty(exports, "__esModule", { value: true }); 7 | exports.setupWalletSelector = void 0; 8 | const core_1 = require("@near-wallet-selector/core"); 9 | const FastAuthWallet_1 = __importDefault(require("./FastAuthWallet")); 10 | const setupWalletSelector = async (params) => { 11 | const { modules = [], localTesting } = params; 12 | // Create a wrapped version of FastAuthWallet that includes localTesting 13 | const fastAuthModuleFactory = async (walletOptions) => { 14 | return (0, FastAuthWallet_1.default)({ 15 | ...walletOptions, 16 | localTesting, // Pass the localTesting flag here 17 | }); 18 | }; 19 | // Initialize the wallet selector with the wrapped FastAuthWallet 20 | const selector = await (0, core_1.setupWalletSelector)({ 21 | ...params, 22 | modules: [fastAuthModuleFactory, ...modules], 23 | }); 24 | return selector; 25 | }; 26 | exports.setupWalletSelector = setupWalletSelector; 27 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/utils/crypto.d.ts: -------------------------------------------------------------------------------- 1 | export declare function deriveEthAddressFromMpcKey(mpcKey: string): string; 2 | -------------------------------------------------------------------------------- /packages/fastauth/lib/lib/utils/crypto.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.deriveEthAddressFromMpcKey = void 0; 7 | const bs58_1 = __importDefault(require("bs58")); 8 | const ethers_1 = require("ethers"); 9 | function deriveEthAddressFromMpcKey(mpcKey) { 10 | // Remove the curve type prefix 11 | const [curveType, keyDataBase58] = mpcKey.split(":"); 12 | if (curveType !== "secp256k1") { 13 | throw new Error("Expected secp256k1 key"); 14 | } 15 | const keyData = bs58_1.default.decode(keyDataBase58); // Key data 16 | console.log("Key data length:", keyData.length); 17 | console.log("Key data (hex):", Buffer.from(keyData).toString("hex")); 18 | if (keyData.length === 64) { 19 | // Uncompressed public key without prefix byte 20 | // Add the '04' prefix to indicate uncompressed key 21 | const uncompressedPublicKeyHex = "04" + Buffer.from(keyData).toString("hex"); 22 | // Compute the Ethereum address using ethers.js 23 | const ethAddress = ethers_1.ethers.computeAddress("0x" + uncompressedPublicKeyHex); 24 | return ethAddress.toLowerCase(); 25 | } 26 | else { 27 | throw new Error("Unsupported public key format. Expected 64 bytes of key data."); 28 | } 29 | } 30 | exports.deriveEthAddressFromMpcKey = deriveEthAddressFromMpcKey; 31 | -------------------------------------------------------------------------------- /packages/fastauth/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@keypom/fastauth", 3 | "version": "0.1.6", 4 | "description": "Core library for FastAuth Login", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "pnpm compile", 8 | "postbuild": "copyfiles -u 2 src/lib/styles.css lib/", 9 | "compile": "tsc -p tsconfig.json", 10 | "deploy:near": "ts-node deploy/main.ts nearSimple", 11 | "deploy:evm": "ts-node deploy/main.ts evmSimple", 12 | "deploy:omni": "ts-node deploy/main.ts omniChainSimple", 13 | "debug:logs": "ts-node deploy/compareLogs.ts", 14 | "broadcast:evm": "ts-node deploy/broadcastSig.ts evmSimple", 15 | "broadcast:near": "ts-node deploy/broadcastSig.ts nearSimple", 16 | "broadcast:omni": "ts-node deploy/broadcastSig.ts omniChainSimple", 17 | "lint:js": "eslint -c ../../.eslintrc.js.yml src/**/*.js --no-eslintrc", 18 | "lint:js:fix": "eslint -c ../../.eslintrc.js.yml src/**/*.js --no-eslintrc --fix", 19 | "lint:ts": "eslint -c ../../.eslintrc.ts.yml src/**/*.ts --no-eslintrc", 20 | "lint:ts:fix": "eslint -c ../../.eslintrc.ts.yml src/**/*.ts --no-eslintrc --fix", 21 | "build-docs": "npx typedoc --options typedoc.json" 22 | }, 23 | "author": "benkurrek", 24 | "license": "MIT", 25 | "dependencies": { 26 | "@near-wallet-selector/core": "^8.9.14", 27 | "@near-wallet-selector/modal-ui": "^8.9.14", 28 | "@react-oauth/google": "^0.12.1", 29 | "bs58": "^6.0.0", 30 | "elliptic": "^6.5.7", 31 | "ethers": "^6.13.4", 32 | "hash.js": "^1.1.7", 33 | "js-sha256": "^0.11.0", 34 | "js-sha3": "^0.9.3", 35 | "near-api-js": "^5.0.1", 36 | "react-google-button": "^0.8.0", 37 | "react-spinners": "^0.14.1", 38 | "tweetnacl-util": "^0.15.1" 39 | }, 40 | "peerDependencies": { 41 | "react": ">=18.0.0", 42 | "react-dom": ">=18.0.0" 43 | }, 44 | "ava": { 45 | "require": [ 46 | "dotenv/config" 47 | ] 48 | }, 49 | "devDependencies": { 50 | "ava": "^4.3.3", 51 | "copyfiles": "^2.4.1", 52 | "dotenv": "^16.0.3", 53 | "eslint": "^8.39.0", 54 | "react": "^18.2.0", 55 | "react-dom": "^18.2.0", 56 | "typedoc": "^0.23.24", 57 | "typescript": "^4.8.4" 58 | }, 59 | "files": [ 60 | "lib/**/*", 61 | "index.js", 62 | "index.ts", 63 | "lib/styles.css" 64 | ] 65 | } 66 | -------------------------------------------------------------------------------- /packages/fastauth/src/index.ts: -------------------------------------------------------------------------------- 1 | // index.ts 2 | 3 | /** 4 | * Main entry point for the Trial Accounts package. 5 | * 6 | * This package provides functions to deploy trial contracts, 7 | * create trials, add trial accounts, activate trial accounts, 8 | * perform actions, and broadcast transactions. 9 | * 10 | * @packageDocumentation 11 | */ 12 | 13 | // index.ts 14 | 15 | export { setupWalletSelector } from "./lib/setupWalletSelector"; 16 | export { setupModal } from "./lib/modal"; 17 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/Storage.ts: -------------------------------------------------------------------------------- 1 | // lib/Storage.ts 2 | 3 | class FastAuthStorage { 4 | private prefix: string; 5 | 6 | constructor(prefix = "FAST_AUTH_WALLET:") { 7 | this.prefix = prefix; 8 | } 9 | 10 | setItem(key: string, value: string) { 11 | localStorage.setItem(this.prefix + key, value); 12 | } 13 | 14 | getItem(key: string): string | null { 15 | return localStorage.getItem(this.prefix + key); 16 | } 17 | 18 | removeItem(key: string) { 19 | localStorage.removeItem(this.prefix + key); 20 | } 21 | 22 | clear() { 23 | // Remove all items with the prefix 24 | Object.keys(localStorage).forEach((key) => { 25 | if (key.startsWith(this.prefix)) { 26 | localStorage.removeItem(key); 27 | } 28 | }); 29 | } 30 | } 31 | 32 | export default new FastAuthStorage(); 33 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/constants.ts: -------------------------------------------------------------------------------- 1 | export const ENV_VARIABLES = { 2 | local: { 3 | MPC_CONTRACT_ID: "v1.signer-prod.testnet", 4 | FASTAUTH_CONTRACT_ID: "1732654372972-fastauth.testnet", 5 | STORAGE_KEY: "FAST_AUTH_WALLET_STATE", 6 | WORKER_BASE_URL: "http://localhost:8787", 7 | }, 8 | testnet: { 9 | MPC_CONTRACT_ID: "v1.signer-prod.testnet", 10 | FASTAUTH_CONTRACT_ID: "1732654372972-fastauth.testnet", 11 | STORAGE_KEY: "FAST_AUTH_WALLET_STATE", 12 | WORKER_BASE_URL: 13 | "https://fastauth-worker-development.keypom.workers.dev", 14 | }, 15 | }; 16 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/icons/AppleIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const AppleIcon: React.FC = () => ( 4 | 11 | 12 | 13 | ); 14 | 15 | export default AppleIcon; 16 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/icons/CloseIcon.tsx: -------------------------------------------------------------------------------- 1 | // lib/icons/CloseIcon.tsx 2 | import React from "react"; 3 | 4 | export const CloseIcon: React.FC = () => ( 5 | 12 | 18 | 24 | 25 | ); 26 | 27 | export default CloseIcon; 28 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/icons/DiscordIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const DiscordIcon: React.FC = () => ( 4 | Discord Icon 9 | ); 10 | 11 | export default DiscordIcon; 12 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/icons/GoogleIcon.tsx: -------------------------------------------------------------------------------- 1 | // src/icons/GoogleIcon.tsx 2 | import React from "react"; 3 | 4 | const GoogleIcon: React.FC = () => ( 5 | 12 | 16 | 20 | 24 | 28 | 29 | ); 30 | 31 | export default GoogleIcon; 32 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/icons/WalletIcon.tsx: -------------------------------------------------------------------------------- 1 | // src/icons/WalletIcon.tsx 2 | import React from "react"; 3 | 4 | const WalletIcon: React.FC = () => ( 5 | 12 | 16 | 17 | 18 | ); 19 | 20 | export default WalletIcon; 21 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/modal.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { WalletSelector } from "@near-wallet-selector/core"; 3 | import type { Root } from "react-dom/client"; 4 | import { createRoot } from "react-dom/client"; 5 | import FastAuthModal from "./FastAuthModal"; 6 | import { 7 | ModalOptions, 8 | setupModal as setupWalletSelectorModal, 9 | } from "@near-wallet-selector/modal-ui"; // Import setupModal 10 | 11 | interface FastAuthModalProps { 12 | show: () => void; 13 | hide: () => void; 14 | } 15 | 16 | let root: Root | null = null; 17 | 18 | export interface FastAuthModalOptions extends ModalOptions { 19 | localTesting?: boolean; 20 | } 21 | 22 | export function setupModal( 23 | selector: WalletSelector, 24 | options: FastAuthModalOptions 25 | ): FastAuthModalProps { 26 | let isVisible = false; 27 | let walletSelectorModal = null; 28 | 29 | const show = () => { 30 | isVisible = true; 31 | renderModal(); 32 | }; 33 | 34 | const hide = () => { 35 | isVisible = false; 36 | renderModal(); 37 | }; 38 | 39 | const renderModal = () => { 40 | const container = 41 | document.getElementById("fastauth-wallet-selector-modal") || 42 | document.createElement("div"); 43 | container.id = "fastauth-wallet-selector-modal"; 44 | document.body.appendChild(container); 45 | 46 | if (!root) { 47 | root = createRoot(container); 48 | } 49 | 50 | if (!walletSelectorModal) { 51 | walletSelectorModal = setupWalletSelectorModal(selector, { 52 | contractId: options.contractId, 53 | methodNames: options.methodNames, 54 | theme: options.theme, 55 | description: options.description, 56 | // Include other options as needed 57 | }); 58 | } 59 | 60 | root.render( 61 | 68 | ); 69 | }; 70 | 71 | return { 72 | show, 73 | hide, 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/models/payload.ts: -------------------------------------------------------------------------------- 1 | export interface NearPayload { 2 | action: NearAction; 3 | nonce: string; 4 | } 5 | 6 | type NearAction = 7 | | { 8 | FunctionCall: { 9 | contract_id: string; 10 | method_name: string; 11 | args: number[]; 12 | gas: string; 13 | deposit: string; 14 | }; 15 | } 16 | | { 17 | Transfer: { 18 | receiver_id: string; 19 | amount: string; 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/mpcUtils/kdf.ts: -------------------------------------------------------------------------------- 1 | import { sha3_256 } from "js-sha3"; 2 | import { ec as EC } from "elliptic"; 3 | import { keccak256 } from "ethers"; 4 | import { base_decode } from "near-api-js/lib/utils/serialize"; 5 | 6 | export function najPublicKeyStrToUncompressedHexPoint( 7 | najPublicKeyStr: string 8 | ): string { 9 | const decodedKey = base_decode(najPublicKeyStr.split(":")[1]!); 10 | return "04" + Buffer.from(decodedKey).toString("hex"); 11 | } 12 | 13 | export function deriveChildPublicKey( 14 | parentUncompressedPublicKeyHex: string, 15 | signerId: string, 16 | path: string = "" 17 | ): string { 18 | const ec = new EC("secp256k1"); 19 | const scalarHex = sha3_256( 20 | `near-mpc-recovery v0.1.0 epsilon derivation:${signerId},${path}` 21 | ); 22 | 23 | const x = parentUncompressedPublicKeyHex.substring(2, 66); 24 | const y = parentUncompressedPublicKeyHex.substring(66); 25 | 26 | // Create a point object from X and Y coordinates 27 | const oldPublicKeyPoint = ec.curve.point(x, y); 28 | 29 | // Multiply the scalar by the generator point G 30 | const scalarTimesG = ec.g.mul(scalarHex); 31 | 32 | // Add the result to the old public key point 33 | const newPublicKeyPoint = oldPublicKeyPoint.add(scalarTimesG); 34 | const newX = newPublicKeyPoint.getX().toString("hex").padStart(64, "0"); 35 | const newY = newPublicKeyPoint.getY().toString("hex").padStart(64, "0"); 36 | return "04" + newX + newY; 37 | } 38 | 39 | export function uncompressedHexPointToEvmAddress(uncompressedHexPoint: string) { 40 | const addressHash = keccak256(`0x${uncompressedHexPoint.slice(2)}`); 41 | // Ethereum address is last 20 bytes of hash (40 characters), prefixed with 0x 42 | return "0x" + addressHash.substring(addressHash.length - 40); 43 | } 44 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/mpcUtils/mockSign.ts: -------------------------------------------------------------------------------- 1 | import { Hex, Signature, toHex } from "viem"; 2 | 3 | export function fromPayload(payload: number[]): Hex { 4 | if (payload.length !== 32) { 5 | throw new Error(`Payload must have 32 bytes: ${payload}`); 6 | } 7 | // Convert number[] back to Uint8Array 8 | return toHex(new Uint8Array(payload)); 9 | } 10 | 11 | /** 12 | * Converts a raw hexadecimal signature into a structured Signature object 13 | * @param hexSignature The raw hexadecimal signature (e.g., '0x...') 14 | * @returns A structured Signature object with fields r, s, v, and yParity 15 | */ 16 | export function hexToSignature(hexSignature: Hex): Signature { 17 | // Strip "0x" prefix if it exists 18 | const cleanedHex = hexSignature.slice(2); 19 | 20 | // Ensure the signature is 65 bytes (130 hex characters) 21 | if (cleanedHex.length !== 130) { 22 | throw new Error( 23 | `Invalid hex signature length: ${cleanedHex.length}. Expected 130 characters (65 bytes).` 24 | ); 25 | } 26 | 27 | // Extract the r, s, and v components from the hex signature 28 | const v = BigInt(`0x${cleanedHex.slice(128, 130)}`); // Last byte (2 hex characters) 29 | return { 30 | r: `0x${cleanedHex.slice(0, 64)}`, // First 32 bytes (64 hex characters) 31 | s: `0x${cleanedHex.slice(64, 128)}`, // Next 32 bytes (64 hex characters), 32 | v, 33 | // Determine yParity based on v (27 or 28 maps to 0 or 1) 34 | yParity: v === 27n ? 0 : v === 28n ? 1 : undefined, 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/mpcUtils/utils.ts: -------------------------------------------------------------------------------- 1 | export * from "./request"; 2 | export * from "./signature"; 3 | export * from "./transaction"; 4 | 5 | export { mockAdapter } from "./mock-sign"; 6 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/setupWalletSelector.ts: -------------------------------------------------------------------------------- 1 | // setupWalletSelector.ts 2 | 3 | import { 4 | setupWalletSelector as baseSetupWalletSelector, 5 | WalletModuleFactory, 6 | WalletSelectorParams, 7 | } from "@near-wallet-selector/core"; 8 | 9 | import FastAuthWallet from "./FastAuthWallet"; 10 | 11 | interface FastAuthWalletParams extends WalletSelectorParams { 12 | localTesting?: boolean; 13 | } 14 | 15 | export const setupWalletSelector = async (params: FastAuthWalletParams) => { 16 | const { modules = [], localTesting } = params; 17 | 18 | // Create a wrapped version of FastAuthWallet that includes localTesting 19 | const fastAuthModuleFactory: WalletModuleFactory = async ( 20 | walletOptions 21 | ) => { 22 | return FastAuthWallet({ 23 | ...walletOptions, 24 | localTesting, // Pass the localTesting flag here 25 | }); 26 | }; 27 | 28 | // Initialize the wallet selector with the wrapped FastAuthWallet 29 | const selector = await baseSetupWalletSelector({ 30 | ...params, 31 | modules: [fastAuthModuleFactory, ...modules], 32 | }); 33 | 34 | return selector; 35 | }; 36 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/utils/authTokens.ts: -------------------------------------------------------------------------------- 1 | export function decodeJwt(token: string): any { 2 | const split = token.split("."); 3 | const payloadEncoded = split[1]; 4 | 5 | const payload = Buffer.from(payloadEncoded, "base64").toString("utf8"); 6 | 7 | return JSON.parse(payload); 8 | } 9 | -------------------------------------------------------------------------------- /packages/fastauth/src/lib/utils/crypto.ts: -------------------------------------------------------------------------------- 1 | import bs58 from "bs58"; 2 | import { ethers } from "ethers"; 3 | 4 | export function deriveEthAddressFromMpcKey(mpcKey: string): string { 5 | // Remove the curve type prefix 6 | const [curveType, keyDataBase58] = mpcKey.split(":"); 7 | if (curveType !== "secp256k1") { 8 | throw new Error("Expected secp256k1 key"); 9 | } 10 | const keyData = bs58.decode(keyDataBase58); // Key data 11 | console.log("Key data length:", keyData.length); 12 | console.log("Key data (hex):", Buffer.from(keyData).toString("hex")); 13 | 14 | if (keyData.length === 64) { 15 | // Uncompressed public key without prefix byte 16 | // Add the '04' prefix to indicate uncompressed key 17 | const uncompressedPublicKeyHex = 18 | "04" + Buffer.from(keyData).toString("hex"); 19 | // Compute the Ethereum address using ethers.js 20 | const ethAddress = ethers.computeAddress( 21 | "0x" + uncompressedPublicKeyHex 22 | ); 23 | return ethAddress.toLowerCase(); 24 | } else { 25 | throw new Error( 26 | "Unsupported public key format. Expected 64 bytes of key data." 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/fastauth/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.node.json", 3 | "compilerOptions": { 4 | "preserveSymlinks": false, 5 | "jsx": "react-jsx", 6 | "outDir": "./lib", 7 | "baseUrl": ".", 8 | "lib": [ 9 | "ES2020", 10 | "DOM" 11 | ], // Add "DOM" here for browser types 12 | "paths": { 13 | "@near-js/types/*": [ 14 | "node_modules/@near-js/types/lib/*" 15 | ], 16 | "@near-js/types/src/provider/protocol": [ 17 | "node_modules/@near-js/types/lib/provider/protocol" 18 | ] 19 | } 20 | }, 21 | "files": [ 22 | "src/index.ts" 23 | ], 24 | "types": [ 25 | "node" 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /packages/fastauth/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "entryPoints": ["./src/index.ts"], 4 | "out": "docs" 5 | } -------------------------------------------------------------------------------- /packages/one-click-connect/lib/core/ext_wallets.d.ts: -------------------------------------------------------------------------------- 1 | import * as nearAPI from "near-api-js"; 2 | import { Transaction as wsTransaction } from "@near-wallet-selector/core"; 3 | export declare const SUPPORTED_EXT_WALLET_DATA: { 4 | testnet: { 5 | "sweat-wallet": {}; 6 | }; 7 | mainnet: { 8 | "sweat-wallet": {}; 9 | }; 10 | }; 11 | /** 12 | * Information to send NEAR wallet for signing transactions and redirecting the browser back to the calling application 13 | */ 14 | interface RequestSignTransactionsOptions { 15 | /** list of transactions to sign */ 16 | transactions: wsTransaction[]; 17 | walletId: string; 18 | accountId: string; 19 | secretKey: string; 20 | near: nearAPI.Near; 21 | walletUrl?: string; 22 | addKey: boolean; 23 | contractId: string; 24 | methodNames: string[]; 25 | allowance: string; 26 | } 27 | /** 28 | * Requests the user to quickly sign for a transaction or batch of transactions by redirecting to the NEAR wallet. 29 | */ 30 | export declare const extSignAndSendTransactions: ({ transactions, walletId, accountId, secretKey, near, walletUrl, addKey, contractId, methodNames, allowance }: RequestSignTransactionsOptions) => Promise; 31 | export {}; 32 | -------------------------------------------------------------------------------- /packages/one-click-connect/lib/core/setup.d.ts: -------------------------------------------------------------------------------- 1 | import type { WalletModuleFactory } from "@near-wallet-selector/core"; 2 | import { KeypomWalletInstant, OneClickParams } from "./types"; 3 | export declare function setupOneClickConnect(params: OneClickParams): WalletModuleFactory; 4 | -------------------------------------------------------------------------------- /packages/one-click-connect/lib/core/types.d.ts: -------------------------------------------------------------------------------- 1 | import { InstantLinkWallet, Network, NetworkId } from "@near-wallet-selector/core"; 2 | import { KeypomWallet } from "./wallet"; 3 | export declare const FAILED_EXECUTION_OUTCOME: any; 4 | export interface SignInOptions { 5 | contractId?: string; 6 | allowance?: string; 7 | methodNames?: string[]; 8 | } 9 | export interface KeypomInitializeOptions { 10 | keypomWallet: KeypomWallet; 11 | } 12 | export interface OneClickParams { 13 | networkId: NetworkId; 14 | contractId: string; 15 | allowance?: string; 16 | methodNames?: string[]; 17 | } 18 | export declare const isOneClickParams: (params: OneClickParams) => boolean; 19 | export type KeypomWalletInstant = InstantLinkWallet & { 20 | networkId: string; 21 | getContractId(): string; 22 | switchAccount(id: string): Promise; 23 | getAccountId(): string; 24 | isSignedIn: () => Promise; 25 | getAvailableBalance: () => Promise; 26 | showModal(): any; 27 | }; 28 | export type AddKeyPermission = "FullAccess" | { 29 | receiverId: string; 30 | allowance?: string; 31 | methodNames?: Array; 32 | }; 33 | export declare const getNetworkPreset: (networkId: NetworkId) => Network; 34 | -------------------------------------------------------------------------------- /packages/one-click-connect/lib/core/types.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.getNetworkPreset = exports.isOneClickParams = exports.FAILED_EXECUTION_OUTCOME = void 0; 4 | exports.FAILED_EXECUTION_OUTCOME = { 5 | final_execution_status: "NONE", 6 | status: { 7 | Failure: { 8 | error_message: "Invalid Trial Action", 9 | error_type: "keypom-trial-error", 10 | }, 11 | }, 12 | transaction: {}, 13 | transaction_outcome: { 14 | id: "", 15 | outcome: { 16 | logs: [], 17 | receipt_ids: [], 18 | tokens_burnt: "0", 19 | executor_id: "", 20 | gas_burnt: 0, 21 | status: { 22 | Failure: { 23 | error_message: "Invalid Trial Action", 24 | error_type: "keypom-trial-error", 25 | }, 26 | }, 27 | }, 28 | }, 29 | receipts_outcome: [ 30 | { 31 | id: "", 32 | outcome: { 33 | logs: [], 34 | receipt_ids: [], 35 | gas_burnt: 0, 36 | tokens_burnt: "0", 37 | executor_id: "", 38 | status: { 39 | Failure: { 40 | error_message: "Invalid Trial Action", 41 | error_type: "keypom-trial-error", 42 | }, 43 | }, 44 | }, 45 | }, 46 | ], 47 | }; 48 | var isOneClickParams = function (params) { 49 | return typeof params.networkId === "string" && 50 | (params.networkId === "testnet" || params.networkId === "mainnet"); 51 | }; 52 | exports.isOneClickParams = isOneClickParams; 53 | var getNetworkPreset = function (networkId) { 54 | switch (networkId) { 55 | case "mainnet": 56 | return { 57 | networkId: networkId, 58 | nodeUrl: "https://rpc.mainnet.near.org", 59 | helperUrl: "https://helper.mainnet.near.org", 60 | explorerUrl: "https://nearblocks.io", 61 | indexerUrl: "https://api.kitwallet.app", 62 | }; 63 | case "testnet": 64 | return { 65 | networkId: networkId, 66 | nodeUrl: "https://rpc.testnet.near.org", 67 | helperUrl: "https://helper.testnet.near.org", 68 | explorerUrl: "https://testnet.nearblocks.io", 69 | indexerUrl: "https://testnet-api.kitwallet.app", 70 | }; 71 | default: 72 | throw Error("Failed to find config for: '".concat(networkId, "'")); 73 | } 74 | }; 75 | exports.getNetworkPreset = getNetworkPreset; 76 | -------------------------------------------------------------------------------- /packages/one-click-connect/lib/core/wallet.d.ts: -------------------------------------------------------------------------------- 1 | import * as nearAPI from "near-api-js"; 2 | import { InstantLinkWalletBehaviour, NetworkId, Transaction } from "@near-wallet-selector/core"; 3 | import { KeypomWalletAccount } from "../utils/selector-utils"; 4 | export declare class KeypomWallet implements InstantLinkWalletBehaviour { 5 | networkId: NetworkId; 6 | accountId: string; 7 | walletId: string; 8 | baseUrl: string; 9 | nearConnection: nearAPI.Near; 10 | keyStore: nearAPI.keyStores.BrowserLocalStorageKeyStore; 11 | contractId: string; 12 | secretKey?: string; 13 | signedIn: boolean; 14 | walletUrl?: string; 15 | addKey: boolean; 16 | methodNames: string[]; 17 | allowance: string; 18 | chainId: string; 19 | constructor({ networkId, nearConnection, keyStore, accountId, secretKey, walletId, baseUrl, contractId, walletUrl, addKey, methodNames, allowance, chainId, }: { 20 | networkId: NetworkId; 21 | nearConnection: any; 22 | keyStore: nearAPI.keyStores.BrowserLocalStorageKeyStore; 23 | accountId: string; 24 | secretKey?: string; 25 | walletId: string; 26 | baseUrl: string; 27 | contractId: string; 28 | walletUrl?: string; 29 | addKey?: boolean; 30 | methodNames?: string[]; 31 | allowance?: string; 32 | chainId?: string; 33 | }); 34 | getAccountId(): string; 35 | isSignedIn(): Promise; 36 | getContractId(): string; 37 | getNearConnection(): nearAPI.Near; 38 | setContractId(contractId?: string): Promise; 39 | signIn(): Promise; 40 | signOut(): Promise; 41 | signAndSendTransaction(params: any): Promise; 42 | signAndSendTransactions(params: { 43 | transactions: Transaction[]; 44 | }): Promise; 45 | verifyOwner(): Promise; 46 | getAvailableBalance(id?: string): Promise; 47 | getAccounts(): Promise; 48 | switchAccount(id: string): Promise; 49 | private internalSignIn; 50 | } 51 | -------------------------------------------------------------------------------- /packages/one-click-connect/lib/index.d.ts: -------------------------------------------------------------------------------- 1 | export type { KeypomWallet } from "./core/wallet"; 2 | export { setupOneClickConnect } from "./core/setup"; 3 | -------------------------------------------------------------------------------- /packages/one-click-connect/lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.setupOneClickConnect = void 0; 4 | var setup_1 = require("./core/setup"); 5 | Object.defineProperty(exports, "setupOneClickConnect", { enumerable: true, get: function () { return setup_1.setupOneClickConnect; } }); 6 | -------------------------------------------------------------------------------- /packages/one-click-connect/lib/utils/one-click-utils.d.ts: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keypom/keypom-js/a422762d00f843fefd4e5f46bba180ae69c376ea/packages/one-click-connect/lib/utils/one-click-utils.d.ts -------------------------------------------------------------------------------- /packages/one-click-connect/lib/utils/selector-utils.d.ts: -------------------------------------------------------------------------------- 1 | import * as nearAPI from "near-api-js"; 2 | import { Action, Network, NetworkId } from "@near-wallet-selector/core"; 3 | import { Transaction as wsTransaction } from "@near-wallet-selector/core"; 4 | import { Action as wsAction } from "@near-wallet-selector/core"; 5 | import { AddKeyPermission } from "@near-wallet-selector/core"; 6 | export declare const ONE_CLICK_URL_REGEX: RegExp; 7 | export declare const KEYPOM_LOCAL_STORAGE_KEY = "keypom-one-click-connect-wallet"; 8 | export declare const NO_CONTRACT_ID = "no-contract"; 9 | export interface KeypomWalletAccount { 10 | accountId: string; 11 | walletId: string; 12 | publicKey?: string; 13 | } 14 | export declare const getLocalStorageKeypomEnv: () => string | null; 15 | export declare const setLocalStorageKeypomEnv: (jsonData: any) => void; 16 | export declare const getLocalStoragePendingKey: (near: nearAPI.Near) => Promise; 17 | export declare const setLocalStoragePendingKey: (jsonData: any) => void; 18 | export declare const getLocalStorageKeypomLak: () => string | null; 19 | export declare const setLocalStorageKeypomLak: (jsonData: any) => void; 20 | interface SignInData { 21 | accountId: string; 22 | secretKey?: string; 23 | walletId: string; 24 | baseUrl: string; 25 | walletUrl?: string; 26 | chainId: string; 27 | addKey: boolean; 28 | } 29 | export declare const tryGetSignInData: ({ networkId, nearConnection, }: { 30 | networkId: string; 31 | nearConnection: nearAPI.Near; 32 | }) => Promise; 33 | /** 34 | * Check if given access key allows the function call or method attempted in transaction 35 | * @param accessKey Array of \{access_key: AccessKey, public_key: PublicKey\} items 36 | * @param receiverId The NEAR account attempting to have access 37 | * @param actions The action(s) needed to be checked for access 38 | */ 39 | export declare const keyHasPermissionForTransaction: (accessKey: any, receiverId: string, actions: Action[]) => Promise; 40 | export declare const parseOneClickSignInFromUrl: ({ baseUrl, delimiter, }: { 41 | baseUrl: string; 42 | delimiter: string; 43 | }) => { 44 | accountId: string; 45 | secretKey?: string | undefined; 46 | walletId: string; 47 | baseUrl: string; 48 | } | null; 49 | export declare const getNetworkPreset: (networkId: NetworkId) => Network; 50 | export declare const getPubFromSecret: (secretKey: string) => string; 51 | export declare const baseDecode: (value: string) => Uint8Array; 52 | export declare const transformTransactions: (transactions: wsTransaction[], account: nearAPI.Account) => Promise; 53 | export declare const createAction: (action: wsAction) => nearAPI.transactions.Action; 54 | export declare const getAccessKey: (permission: AddKeyPermission) => nearAPI.transactions.AccessKey; 55 | export {}; 56 | -------------------------------------------------------------------------------- /packages/one-click-connect/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@keypom/one-click-connect", 3 | "version": "1.0.1", 4 | "description": "OneClick Connect Wallet Selector Plugin", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "pnpm compile", 8 | "build-test": "pnpm compile && ../../buildMove.sh", 9 | "build-test-gb": "pnpm compile && ../../buildMoveGuest.sh", 10 | "compile": "tsc -p tsconfig.json", 11 | "lint:js": "eslint -c ../../.eslintrc.js.yml src/**/*.js --no-eslintrc", 12 | "lint:js:fix": "eslint -c ../../.eslintrc.js.yml src/**/*.js --no-eslintrc --fix", 13 | "lint:ts": "eslint -c ../../.eslintrc.ts.yml src/**/*.ts --no-eslintrc", 14 | "lint:ts:fix": "eslint -c ../../.eslintrc.ts.yml src/**/*.ts --no-eslintrc --fix", 15 | "create:trial-accounts": "yarn build && node test/trial-accounts.ts", 16 | "create:instant-sign-in": "yarn build && node test/instant-sign-in.ts", 17 | "build-docs": "npx typedoc --options typedoc.json" 18 | }, 19 | "author": "benkurrek, mattlockyer", 20 | "license": "MIT", 21 | "ava": { 22 | "require": [ 23 | "dotenv/config" 24 | ] 25 | }, 26 | "dependencies": { 27 | "@near-wallet-selector/core": "8.9.5", 28 | "@near-wallet-selector/wallet-utils": "8.9.5", 29 | "bn.js": "^5.2.1" 30 | }, 31 | "devDependencies": { 32 | "@types/react": "^18.0.26", 33 | "ava": "^4.3.3", 34 | "near-api-js": "^2.1.3", 35 | "react": "^18.2.0", 36 | "react-dom": "18.2.0", 37 | "typedoc": "^0.23.24", 38 | "typescript": "^4.8.4" 39 | }, 40 | "peerDependencies": { 41 | "near-api-js": "^2.1.3" 42 | }, 43 | "files": [ 44 | "lib" 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /packages/one-click-connect/src/core/types.ts: -------------------------------------------------------------------------------- 1 | import { 2 | InstantLinkWallet, 3 | Network, 4 | NetworkId, 5 | } from "@near-wallet-selector/core"; 6 | import { KeypomWallet } from "./wallet"; 7 | 8 | export const FAILED_EXECUTION_OUTCOME: any = { 9 | final_execution_status: "NONE", 10 | status: { 11 | Failure: { 12 | error_message: "Invalid Trial Action", 13 | error_type: "keypom-trial-error", 14 | }, 15 | }, 16 | transaction: {}, 17 | transaction_outcome: { 18 | id: "", 19 | outcome: { 20 | logs: [], 21 | receipt_ids: [], 22 | tokens_burnt: "0", 23 | executor_id: "", 24 | gas_burnt: 0, 25 | status: { 26 | Failure: { 27 | error_message: "Invalid Trial Action", 28 | error_type: "keypom-trial-error", 29 | }, 30 | }, 31 | }, 32 | }, 33 | receipts_outcome: [ 34 | { 35 | id: "", 36 | outcome: { 37 | logs: [], 38 | receipt_ids: [], 39 | gas_burnt: 0, 40 | tokens_burnt: "0", 41 | executor_id: "", 42 | status: { 43 | Failure: { 44 | error_message: "Invalid Trial Action", 45 | error_type: "keypom-trial-error", 46 | }, 47 | }, 48 | }, 49 | }, 50 | ], 51 | }; 52 | 53 | export interface SignInOptions { 54 | contractId?: string; 55 | allowance?: string; 56 | methodNames?: string[]; 57 | } 58 | 59 | export interface KeypomInitializeOptions { 60 | keypomWallet: KeypomWallet; 61 | } 62 | 63 | export interface OneClickParams { 64 | networkId: NetworkId; 65 | contractId: string; 66 | allowance?: string; 67 | methodNames?: string[]; 68 | } 69 | 70 | export const isOneClickParams = (params: OneClickParams): boolean => 71 | typeof params.networkId === "string" && 72 | (params.networkId === "testnet" || params.networkId === "mainnet"); 73 | 74 | export type KeypomWalletInstant = InstantLinkWallet & { 75 | networkId: string; 76 | getContractId(): string; 77 | switchAccount(id: string): Promise; 78 | getAccountId(): string; 79 | isSignedIn: () => Promise; 80 | getAvailableBalance: () => Promise; 81 | showModal(); 82 | }; 83 | 84 | export type AddKeyPermission = 85 | | "FullAccess" 86 | | { 87 | receiverId: string; 88 | allowance?: string; 89 | methodNames?: Array; 90 | }; 91 | 92 | export const getNetworkPreset = (networkId: NetworkId): Network => { 93 | switch (networkId) { 94 | case "mainnet": 95 | return { 96 | networkId, 97 | nodeUrl: "https://rpc.mainnet.near.org", 98 | helperUrl: "https://helper.mainnet.near.org", 99 | explorerUrl: "https://nearblocks.io", 100 | indexerUrl: "https://api.kitwallet.app", 101 | }; 102 | case "testnet": 103 | return { 104 | networkId, 105 | nodeUrl: "https://rpc.testnet.near.org", 106 | helperUrl: "https://helper.testnet.near.org", 107 | explorerUrl: "https://testnet.nearblocks.io", 108 | indexerUrl: "https://testnet-api.kitwallet.app", 109 | }; 110 | default: 111 | throw Error(`Failed to find config for: '${networkId}'`); 112 | } 113 | }; 114 | -------------------------------------------------------------------------------- /packages/one-click-connect/src/index.ts: -------------------------------------------------------------------------------- 1 | export type { KeypomWallet } from "./core/wallet"; 2 | export { setupOneClickConnect } from "./core/setup"; 3 | -------------------------------------------------------------------------------- /packages/one-click-connect/test/ext-wasm/trial-accounts.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keypom/keypom-js/a422762d00f843fefd4e5f46bba180ae69c376ea/packages/one-click-connect/test/ext-wasm/trial-accounts.wasm -------------------------------------------------------------------------------- /packages/one-click-connect/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "entryPoints": ["./src/index.ts"], 4 | "out": "docs" 5 | } -------------------------------------------------------------------------------- /packages/trial-accounts/data/clientLog.json: -------------------------------------------------------------------------------- 1 | "" -------------------------------------------------------------------------------- /packages/trial-accounts/data/signatures.json: -------------------------------------------------------------------------------- 1 | { 2 | "signatures": [ 3 | { 4 | "big_r": { 5 | "affine_point": "022EF2BB384895A50397E35CFF82BC5119A7E660264E406290F6F46D61A3E14B16" 6 | }, 7 | "s": { 8 | "scalar": "18E21C933D2979C01823289D88F13E8D4CFCA19D4094070FDD103130E0F77670" 9 | }, 10 | "recovery_id": 1 11 | } 12 | ], 13 | "txnDatas": [ 14 | { 15 | "nonce": "178042356000001", 16 | "blockHash": "3gZeXQ2w3hLLm2zYCFGAJD9B7UqsEDjs1bB3SoKgPjRM" 17 | } 18 | ] 19 | } -------------------------------------------------------------------------------- /packages/trial-accounts/data/trialData.json: -------------------------------------------------------------------------------- 1 | { 2 | "trialId": 20, 3 | "trialContractId": "1729530318593-trial-contract.testnet", 4 | "trialKeys": [ 5 | { 6 | "derivationPath": "ed25519:2k1tAe5W9M4f1pr6RJ1LJAsXAcYruXCyMK2LNtHJhAKg", 7 | "trialAccountSecretKey": "ed25519:3uRPfK5YWAnmGP15dT9aZWmkEQwkaN7u3eqb4PZvhuBdmUKxtADoBK9DzYMFryus9r5GJZfpqPaeM88PZvKcG9T4", 8 | "trialAccountPublicKey": "ed25519:2k1tAe5W9M4f1pr6RJ1LJAsXAcYruXCyMK2LNtHJhAKg", 9 | "mpcKey": "secp256k1:3XUjKVSqVvuTKkiZS3xzHEaot7gqM9YeqmGEgQoppt6QNt4gBKm2EfHDEquAW3StQMJgPrJ7wokYY9Pzjeg7zLmR" 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/abis/baseGuestbook.ts: -------------------------------------------------------------------------------- 1 | export const BASE_GUESTBOOK_ABI = [ 2 | "function setMessage(string _message)", 3 | "function getMessage() view returns (string)", 4 | ]; 5 | -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/abis/baseNFT.ts: -------------------------------------------------------------------------------- 1 | export const BASE_NFT_ABI = [ 2 | "function lazyMint(address to, uint256 series, uint256 quantity, bytes data)", 3 | "function batchLazyMint(address to, uint256[] seriesIds, uint256[] amounts, bytes data)", 4 | "function multiAddressLazyMint(address[] addresses, uint256[] seriesIds, bytes data)", 5 | "function multiAddressLazyMintTest(uint256[] bar)", 6 | "function approveCreator(address creator)", 7 | "function revokeCreator(address creator)", 8 | "function setBaseURI(string baseURI)", 9 | "function initializeSeries(uint256 maxSupply, string token_uri)", 10 | ]; 11 | -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/compareLogs.ts: -------------------------------------------------------------------------------- 1 | import { readFromFile } from "./utils/fileOps"; 2 | import { compareAndLog } from "./utils/logUtils"; 3 | 4 | /** 5 | * Compares contract logs with client logs and logs the results. 6 | */ 7 | function compareLogs() { 8 | console.log("Starting log comparison...\n"); 9 | const dataDir = "./data"; 10 | 11 | // Read the contract logs 12 | const contractLog = readFromFile(dataDir, "contractLogs.json"); 13 | 14 | // Read the client logs 15 | const clientLog = readFromFile(dataDir, "clientLog.json"); 16 | 17 | console.log("Comparing Chain ID..."); 18 | compareAndLog( 19 | "Chain ID", 20 | contractLog["Chain ID"].toString(), 21 | clientLog["Chain ID"].toString() 22 | ); 23 | 24 | console.log("\nComparing Nonce..."); 25 | compareAndLog( 26 | "Nonce", 27 | contractLog["Nonce"].toString(), 28 | clientLog["Nonce"].toString() 29 | ); 30 | 31 | console.log("\nComparing Max Priority Fee Per Gas..."); 32 | compareAndLog( 33 | "Max Priority Fee Per Gas", 34 | contractLog["Max Priority Fee Per Gas"], 35 | clientLog["Max Priority Fee Per Gas"] 36 | ); 37 | 38 | console.log("\nComparing Max Fee Per Gas..."); 39 | compareAndLog( 40 | "Max Fee Per Gas", 41 | contractLog["Max Fee Per Gas"], 42 | clientLog["Max Fee Per Gas"] 43 | ); 44 | 45 | console.log("\nComparing Gas Limit..."); 46 | compareAndLog( 47 | "Gas Limit", 48 | contractLog["Gas Limit"], 49 | clientLog["Gas Limit"] 50 | ); 51 | 52 | console.log("\nComparing Contract Address..."); 53 | compareAndLog( 54 | "Contract Address", 55 | contractLog["Contract Address"], 56 | clientLog["Contract Address"], 57 | (value) => { 58 | // Convert byte array to hex string if necessary 59 | if (Array.isArray(value)) { 60 | return "0x" + Buffer.from(value).toString("hex"); 61 | } 62 | return value.toLowerCase(); 63 | } 64 | ); 65 | 66 | console.log("\nComparing Value..."); 67 | compareAndLog("Value", contractLog["Value"], clientLog["Value"]); 68 | 69 | console.log("\nComparing Input Data..."); 70 | compareAndLog( 71 | "Input Data", 72 | contractLog["Input Data"], 73 | clientLog["Input Data"] 74 | ); 75 | 76 | console.log("\nComparing Hashed Payload..."); 77 | compareAndLog( 78 | "Hashed Payload", 79 | contractLog["Hashed Payload"], 80 | clientLog["Hashed Payload"] 81 | ); 82 | 83 | console.log("\nLog comparison complete."); 84 | } 85 | 86 | // Run the comparison 87 | compareLogs(); 88 | -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/configs/evmSimple.ts: -------------------------------------------------------------------------------- 1 | // src/configs/evmSimple.ts 2 | 3 | import path from "path"; 4 | import os from "os"; 5 | import { Config } from "./type"; 6 | import { TrialData, ActionToPerform, AccessList } from "../../src/index"; 7 | import { BASE_GUESTBOOK_ABI } from "../abis/baseGuestbook"; 8 | import { parseEther } from "ethers"; 9 | import { UnencryptedFileSystemKeyStore } from "near-api-js/lib/key_stores"; 10 | 11 | const homedir = os.homedir(); 12 | const CREDENTIALS_DIR = ".near-credentials"; 13 | const credentialsPath = path.join(homedir, CREDENTIALS_DIR); 14 | 15 | export const config: Config = { 16 | networkId: "testnet", 17 | trialContractId: "1729530318593-trial-contract.testnet", 18 | signerAccountId: "benjiman.testnet", 19 | keyStore: new UnencryptedFileSystemKeyStore(credentialsPath), 20 | mpcContractId: "v1.signer-prod.testnet", 21 | numberOfKeys: 1, 22 | dataDir: "./data", 23 | }; 24 | 25 | export const trialData: TrialData = { 26 | constraintsByChainId: { 27 | EVM: { 28 | chainId: 421614, 29 | allowedMethods: ["increment"], 30 | allowedContracts: ["0x6d21161d1D17cDCA58707829E4d57D5a4EfE5489"], 31 | maxGas: 1000000, // Optional 32 | maxValue: "0", // Optional 33 | initialDeposit: parseEther("0.004"), // roughly 15$ 34 | }, 35 | }, 36 | usageConstraints: null, 37 | interactionLimits: null, 38 | exitConditions: null, 39 | expirationTime: null, 40 | }; 41 | 42 | // ARGUMENTS TO THE FUNCTION CALL 43 | const _message = "Hello from the MPC Trial Account EVM Config!"; 44 | const args = [_message]; 45 | 46 | const accessList: AccessList = []; 47 | export const actionsToPerform: ActionToPerform[] = [ 48 | { 49 | chain: "EVM", 50 | chainId: 421614, 51 | targetContractId: "0xdf5c3bd628a11C97BB25d441D8b6d9Ce974dc552", 52 | methodName: "setMessage", 53 | args, 54 | abi: BASE_GUESTBOOK_ABI, // Provide the ABI of the contract 55 | value: "0", // If no ETH is sent along with the transaction 56 | accessList: accessList, 57 | }, 58 | ]; 59 | -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/configs/nearSimple.ts: -------------------------------------------------------------------------------- 1 | // src/configs/simple.ts 2 | 3 | import { UnencryptedFileSystemKeyStore } from "near-api-js/lib/key_stores"; 4 | import path from "path"; 5 | import os from "os"; 6 | import { Config } from "./type"; 7 | import { TrialData, ActionToPerform } from "../../src/index"; 8 | import { parseNearAmount } from "near-api-js/lib/utils/format"; 9 | 10 | const homedir = os.homedir(); 11 | const CREDENTIALS_DIR = ".near-credentials"; 12 | const credentialsPath = path.join(homedir, CREDENTIALS_DIR); 13 | 14 | export const config: Config = { 15 | networkId: "testnet", 16 | trialContractId: "1729530318593-trial-contract.testnet", 17 | signerAccountId: "benjiman.testnet", 18 | keyStore: new UnencryptedFileSystemKeyStore(credentialsPath), 19 | mpcContractId: "v1.signer-prod.testnet", 20 | numberOfKeys: 1, 21 | dataDir: "./data", 22 | }; 23 | 24 | export const trialData: TrialData = { 25 | constraintsByChainId: { 26 | NEAR: { 27 | allowedMethods: ["add_message"], 28 | allowedContracts: ["guestbook.near-examples.testnet"], 29 | maxGas: null, 30 | maxDeposit: null, 31 | initialDeposit: parseNearAmount("10")!, 32 | }, 33 | }, 34 | usageConstraints: null, 35 | interactionLimits: null, 36 | exitConditions: null, 37 | expirationTime: null, 38 | }; 39 | 40 | export const actionsToPerform: ActionToPerform[] = [ 41 | { 42 | chain: "NEAR", 43 | targetContractId: "guestbook.near-examples.testnet", 44 | methodName: "add_message", 45 | args: { text: "Hello from the MPC Trial Account Near Config!" }, 46 | attachedDepositNear: "1", 47 | gas: "300000000000000", 48 | }, 49 | ]; 50 | -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/configs/omniChainSimple.ts: -------------------------------------------------------------------------------- 1 | // src/configs/onniChainSimple.ts 2 | 3 | import path from "path"; 4 | import os from "os"; 5 | import { Config } from "./type"; 6 | import { TrialData, ActionToPerform, AccessList } from "../../src/index"; 7 | import { BASE_GUESTBOOK_ABI } from "../abis/baseGuestbook"; 8 | import { parseEther } from "ethers"; 9 | import { UnencryptedFileSystemKeyStore } from "near-api-js/lib/key_stores"; 10 | import { parseNearAmount } from "near-api-js/lib/utils/format"; 11 | 12 | const homedir = os.homedir(); 13 | const CREDENTIALS_DIR = ".near-credentials"; 14 | const credentialsPath = path.join(homedir, CREDENTIALS_DIR); 15 | 16 | export const config: Config = { 17 | networkId: "testnet", 18 | trialContractId: "1729530318593-trial-contract.testnet", 19 | signerAccountId: "benjiman.testnet", 20 | keyStore: new UnencryptedFileSystemKeyStore(credentialsPath), 21 | mpcContractId: "v1.signer-prod.testnet", 22 | numberOfKeys: 1, 23 | dataDir: "./data", 24 | }; 25 | 26 | export const trialData: TrialData = { 27 | constraintsByChainId: { 28 | EVM: { 29 | chainId: 421614, 30 | allowedMethods: ["increment"], 31 | allowedContracts: ["0x6d21161d1D17cDCA58707829E4d57D5a4EfE5489"], 32 | maxGas: 1000000, // Optional 33 | maxValue: "0", // Optional 34 | initialDeposit: parseEther("0.004"), // roughly 15$ 35 | }, 36 | NEAR: { 37 | allowedMethods: ["add_message"], 38 | allowedContracts: ["guestbook.near-examples.testnet"], 39 | maxGas: null, 40 | maxDeposit: null, 41 | initialDeposit: parseNearAmount("10")!, 42 | }, 43 | }, 44 | usageConstraints: null, 45 | interactionLimits: null, 46 | exitConditions: null, 47 | expirationTime: null, 48 | }; 49 | 50 | // ARGUMENTS TO THE FUNCTION CALL 51 | const _message = "Hello from the MPC Trial Account EVM Config!"; 52 | const evmArgs = [_message]; 53 | 54 | const accessList: AccessList = []; 55 | export const actionsToPerform: ActionToPerform[] = [ 56 | { 57 | chain: "NEAR", 58 | targetContractId: "guestbook.near-examples.testnet", 59 | methodName: "add_message", 60 | args: { text: "Hello from the MPC Trial Account Near Config!" }, 61 | attachedDepositNear: "1", 62 | gas: "300000000000000", 63 | }, 64 | { 65 | chain: "EVM", 66 | chainId: 421614, 67 | targetContractId: "0xdf5c3bd628a11C97BB25d441D8b6d9Ce974dc552", 68 | methodName: "setMessage", 69 | args: evmArgs, 70 | abi: BASE_GUESTBOOK_ABI, // Provide the ABI of the contract 71 | value: "0", // If no ETH is sent along with the transaction 72 | accessList: accessList, 73 | }, 74 | ]; 75 | -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/configs/type.ts: -------------------------------------------------------------------------------- 1 | import { UnencryptedFileSystemKeyStore } from "@near-js/keystores-node"; 2 | 3 | /** 4 | * Configuration required to initialize the NEAR connection and other parameters. 5 | */ 6 | export interface Config { 7 | trialContractId: string; 8 | networkId: string; 9 | signerAccountId: string; 10 | keyStore: UnencryptedFileSystemKeyStore; 11 | mpcContractId: string; 12 | numberOfKeys: number; 13 | dataDir: string; 14 | } 15 | -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/utils/evmUtils.ts: -------------------------------------------------------------------------------- 1 | import { ethers, JsonRpcProvider } from "ethers"; 2 | 3 | export function getSponsorEVMWallet( 4 | evmPrivateKey: string, 5 | providerUrl: string, 6 | chainId: string 7 | ) { 8 | // Convert the hex private key string into a Uint8Array 9 | const hexPrivateKey = evmPrivateKey.startsWith("0x") 10 | ? evmPrivateKey.slice(2) 11 | : evmPrivateKey; 12 | 13 | const privateKeyBytes = Uint8Array.from(Buffer.from(hexPrivateKey, "hex")); 14 | 15 | // Initialize provider 16 | const provider = new JsonRpcProvider(providerUrl, parseInt(chainId, 10)); 17 | 18 | // Create the wallet using the private key bytes 19 | const SPONSOR_WALLET = new ethers.Wallet( 20 | new ethers.SigningKey(privateKeyBytes), 21 | provider 22 | ); 23 | 24 | return SPONSOR_WALLET; 25 | } 26 | -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/utils/fileOps.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | 4 | /** 5 | * Ensures that a directory exists; if not, it creates the directory. 6 | * 7 | * @param dirPath - The path to the directory. 8 | */ 9 | function ensureDirExists(dirPath: string): void { 10 | if (!fs.existsSync(dirPath)) { 11 | fs.mkdirSync(dirPath, { recursive: true }); 12 | } 13 | } 14 | 15 | /** 16 | * Writes an object to a JSON file. 17 | * 18 | * @param filePath - The path to the JSON file. 19 | * @param data - The data to write to the file. 20 | */ 21 | function writeJSONFile(filePath: string, data: any): void { 22 | fs.writeFileSync(filePath, JSON.stringify(data, null, 2)); 23 | } 24 | 25 | /** 26 | * Writes an object to a JSON file. 27 | * @param filePath - The path to the JSON file. 28 | * @param data - The data to write to the file. 29 | * @throws If the file cannot be written. 30 | * @throws If the file contains invalid JSON. 31 | */ 32 | export function writeToFile( 33 | data: any, 34 | dataDir: string, 35 | fileName: string, 36 | ): void { 37 | // Ensure the data directory exists 38 | ensureDirExists(dataDir); 39 | 40 | // Save the trial keys to a file 41 | const filePath = path.join(dataDir, fileName); 42 | writeJSONFile(filePath, data); 43 | } 44 | 45 | /** 46 | * Reads an object from a JSON file. 47 | * @param filePath - The path to the JSON file. 48 | * @returns The object read from the file. 49 | * @throws If the file does not exist or cannot be read. 50 | * @throws If the file contains invalid JSON. 51 | */ 52 | export function readFromFile(dataDir: string, fileName: string): any { 53 | const filePath = path.join(dataDir, fileName); 54 | return JSON.parse(fs.readFileSync(filePath, "utf-8")); 55 | } 56 | -------------------------------------------------------------------------------- /packages/trial-accounts/deploy/utils/nearUtils.ts: -------------------------------------------------------------------------------- 1 | import { FinalExecutionOutcome } from "@near-wallet-selector/core"; 2 | import { Near } from "near-api-js"; 3 | import { Config } from "../configs/type"; 4 | 5 | /** 6 | * Initializes a NEAR connection using the provided configuration. 7 | * 8 | * @param config - The configuration object containing network ID, key store, etc. 9 | * @returns A Promise that resolves to a Near instance. 10 | */ 11 | export async function initNear(config: Config): Promise { 12 | const nearConfig = { 13 | networkId: config.networkId, 14 | nodeUrl: `https://rpc.${config.networkId}.near.org`, 15 | keyStore: config.keyStore, 16 | }; 17 | const near = new Near(nearConfig); 18 | return near; 19 | } 20 | 21 | export function isFinalExecutionOutcome( 22 | result: any 23 | ): result is FinalExecutionOutcome { 24 | return ( 25 | result && 26 | typeof result === "object" && 27 | "final_execution_status" in result && 28 | "status" in result && 29 | "transaction" in result && 30 | "transaction_outcome" in result && 31 | "receipts_outcome" in result 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Main entry point for the Trial Accounts package. 3 | * 4 | * This package provides functions to deploy trial contracts, 5 | * create trials, add trial accounts, activate trial accounts, 6 | * perform actions, and broadcast transactions. 7 | * 8 | * @packageDocumentation 9 | */ 10 | export { TrialAccountManager } from "./lib/TrialAccountManager"; 11 | export { setupKeypomTrialSelector } from "./lib/wallet-selector/setup"; 12 | export * from "./lib/types"; 13 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // index.ts 3 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 4 | if (k2 === undefined) k2 = k; 5 | var desc = Object.getOwnPropertyDescriptor(m, k); 6 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 7 | desc = { enumerable: true, get: function() { return m[k]; } }; 8 | } 9 | Object.defineProperty(o, k2, desc); 10 | }) : (function(o, m, k, k2) { 11 | if (k2 === undefined) k2 = k; 12 | o[k2] = m[k]; 13 | })); 14 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 15 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 16 | }; 17 | Object.defineProperty(exports, "__esModule", { value: true }); 18 | exports.setupKeypomTrialSelector = exports.TrialAccountManager = void 0; 19 | /** 20 | * Main entry point for the Trial Accounts package. 21 | * 22 | * This package provides functions to deploy trial contracts, 23 | * create trials, add trial accounts, activate trial accounts, 24 | * perform actions, and broadcast transactions. 25 | * 26 | * @packageDocumentation 27 | */ 28 | var TrialAccountManager_1 = require("./lib/TrialAccountManager"); 29 | Object.defineProperty(exports, "TrialAccountManager", { enumerable: true, get: function () { return TrialAccountManager_1.TrialAccountManager; } }); 30 | var setup_1 = require("./lib/wallet-selector/setup"); 31 | Object.defineProperty(exports, "setupKeypomTrialSelector", { enumerable: true, get: function () { return setup_1.setupKeypomTrialSelector; } }); 32 | // Export types for user convenience 33 | __exportStar(require("./lib/types"), exports); 34 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/activateTrial.d.ts: -------------------------------------------------------------------------------- 1 | import { Near } from "near-api-js"; 2 | import { KeyPairString } from "near-api-js/lib/utils"; 3 | interface ActivateTrialAccountsParams { 4 | near: Near; 5 | trialContractId: string; 6 | trialAccountIds: string[]; 7 | trialAccountSecretKeys: KeyPairString[]; 8 | chainIds: string[]; 9 | } 10 | /** 11 | * Activates trial accounts on the trial contract. 12 | * 13 | * @param params - The parameters required to activate trial accounts. 14 | * @returns A Promise that resolves when all accounts are activated. 15 | * @throws Will throw an error if activation of any trial account fails. 16 | */ 17 | export declare function activateTrialAccounts(params: ActivateTrialAccountsParams): Promise; 18 | export {}; 19 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/activateTrial.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // activateTrial.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | exports.activateTrialAccounts = void 0; 5 | const utils_1 = require("near-api-js/lib/utils"); 6 | const near_1 = require("./networks/near"); 7 | /** 8 | * Activates trial accounts on the trial contract. 9 | * 10 | * @param params - The parameters required to activate trial accounts. 11 | * @returns A Promise that resolves when all accounts are activated. 12 | * @throws Will throw an error if activation of any trial account fails. 13 | */ 14 | async function activateTrialAccounts(params) { 15 | const { trialContractId, trialAccountIds, near, trialAccountSecretKeys } = params; 16 | for (let i = 0; i < trialAccountIds.length; i++) { 17 | const trialAccountId = trialAccountIds[i]; 18 | const trialKey = trialAccountSecretKeys[i]; 19 | const chainId = params.chainIds[i]; 20 | // Set the trial key in the keyStore 21 | const keyStore = near.connection.signer.keyStore; 22 | await keyStore.setKey(near.connection.networkId, trialContractId, utils_1.KeyPair.fromString(trialKey)); 23 | const signerAccount = await near.account(trialContractId); 24 | const result = await (0, near_1.sendTransaction)({ 25 | signerAccount, 26 | receiverId: trialContractId, 27 | methodName: "activate_trial", 28 | args: { 29 | new_account_id: trialAccountId, 30 | chain_id: chainId.toString(), 31 | }, 32 | deposit: "0", 33 | gas: "300000000000000", 34 | }); 35 | if (!result) { 36 | throw new Error(`Failed to activate trial account: ${trialAccountId}`); 37 | } 38 | } 39 | } 40 | exports.activateTrialAccounts = activateTrialAccounts; 41 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/addTrialKeys.d.ts: -------------------------------------------------------------------------------- 1 | import { TrialKey } from "./types"; 2 | interface AddTrialAccountsParams { 3 | trialContractId: string; 4 | mpcContractId: string; 5 | numberOfKeys: number; 6 | viewFunction: any; 7 | } 8 | /** 9 | * Generates the trial key data needed to add trial accounts. 10 | * 11 | * @param params - The number of keys to generate. 12 | * @returns A Promise that resolves to an array of TrialKey objects. 13 | */ 14 | export declare function generateTrialKeys(params: AddTrialAccountsParams): Promise; 15 | export {}; 16 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/addTrialKeys.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // addTrialKeys.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | exports.generateTrialKeys = void 0; 5 | const near_api_js_1 = require("near-api-js"); 6 | /** 7 | * Generates the trial key data needed to add trial accounts. 8 | * 9 | * @param params - The number of keys to generate. 10 | * @returns A Promise that resolves to an array of TrialKey objects. 11 | */ 12 | async function generateTrialKeys(params) { 13 | const { trialContractId, mpcContractId, numberOfKeys, viewFunction } = params; 14 | const trialKeys = []; 15 | for (let i = 0; i < numberOfKeys; i++) { 16 | // Generate a new key pair 17 | const keyPair = near_api_js_1.KeyPair.fromRandom("ed25519"); 18 | // Derive the MPC public key 19 | const derivationPath = keyPair.getPublicKey().toString(); 20 | const mpcPublicKey = await viewFunction({ 21 | contractId: mpcContractId, 22 | methodName: "derived_public_key", 23 | args: { 24 | path: derivationPath, 25 | predecessor: trialContractId, 26 | }, 27 | }); 28 | trialKeys.push({ 29 | derivationPath, 30 | trialAccountSecretKey: keyPair.toString(), 31 | trialAccountPublicKey: keyPair.getPublicKey().toString(), 32 | mpcKey: mpcPublicKey, 33 | }); 34 | } 35 | return trialKeys; 36 | } 37 | exports.generateTrialKeys = generateTrialKeys; 38 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/broadcastTransaction.d.ts: -------------------------------------------------------------------------------- 1 | import { ActionToPerform, MPCSignature } from "./types"; 2 | import { TransactionResponse } from "ethers"; 3 | import { Near } from "near-api-js"; 4 | import { TransactionData } from "./performAction"; 5 | import { FinalExecutionOutcome } from "@near-wallet-selector/core"; 6 | interface BroadcastTransactionParams { 7 | nearConnection: Near; 8 | chainId: string; 9 | signerAccountId: string; 10 | actionToPerform: ActionToPerform; 11 | signatureResult: MPCSignature; 12 | txnData: TransactionData; 13 | mpcPublicKey: string; 14 | providerUrl?: string; 15 | } 16 | /** 17 | * Broadcasts a signed transaction to the NEAR or EVM network. 18 | * 19 | * @param params - The parameters required to broadcast the transaction. 20 | * @returns A Promise that resolves when the transaction is broadcasted. 21 | * @throws Will throw an error if broadcasting fails. 22 | */ 23 | export declare function broadcastTransaction(params: BroadcastTransactionParams): Promise<{ 24 | result: TransactionResponse | FinalExecutionOutcome; 25 | clientLog: any; 26 | }>; 27 | export {}; 28 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/createTrial.d.ts: -------------------------------------------------------------------------------- 1 | import { TrialData } from "./types"; 2 | /** 3 | * Generates the arguments for creating a trial. 4 | * 5 | * @param params - The parameters required to create a trial. 6 | * @returns A Record containing the arguments for creating a trial. 7 | */ 8 | export declare function getCreateTrialParams(trialData: TrialData): Record; 9 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/createTrial.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // lib/createTrial.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | exports.getCreateTrialParams = void 0; 5 | const types_1 = require("./types"); 6 | /** 7 | * Generates the arguments for creating a trial. 8 | * 9 | * @param params - The parameters required to create a trial. 10 | * @returns A Record containing the arguments for creating a trial. 11 | */ 12 | function getCreateTrialParams(trialData) { 13 | // Type guard to check if value is ExtEVMConstraints 14 | const isExtEVMConstraints = (value) => { 15 | return value.chainId !== undefined; 16 | }; 17 | // Transform constraintsByChainId to use chain ID directly if it's EVM 18 | const transformedConstraints = Object.entries(trialData.constraintsByChainId).reduce((acc, [key, value]) => { 19 | if (key === "EVM" && isExtEVMConstraints(value)) { 20 | // Now TypeScript knows that value is ExtEVMConstraints 21 | const evmConstraints = value; 22 | acc[evmConstraints.chainId] = { ...evmConstraints }; 23 | acc[evmConstraints.chainId].initialDeposit = 24 | acc[evmConstraints.chainId].initialDeposit.toString(); 25 | // @ts-ignore 26 | delete acc[evmConstraints.chainId].chainId; // Remove chainId as it's now used as the key 27 | } 28 | else { 29 | acc[key] = value; 30 | } 31 | return acc; 32 | }, {}); 33 | const { constraintsByChainId, ...restTrialData } = trialData; 34 | const snakeCaseArgs = (0, types_1.toSnakeCase)({ 35 | ...restTrialData, 36 | chain_constraints: transformedConstraints, // Use transformed constraints here 37 | }); 38 | return snakeCaseArgs; 39 | } 40 | exports.getCreateTrialParams = getCreateTrialParams; 41 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/cryptoUtils.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | import { Signature } from "near-api-js/lib/transaction"; 4 | /** 5 | * Creates a NEAR Signature object from r, s, and recovery ID. 6 | * @param r - The r component of the signature. 7 | * @param s - The s component of the signature. 8 | * @returns A NEAR Signature object. 9 | */ 10 | export declare function createSignature(r: string, s: string): Signature; 11 | /** 12 | * Hashes the serialized transaction using SHA-256. 13 | * @param serializedTx - The serialized transaction bytes. 14 | * @returns The SHA-256 hash as a Uint8Array. 15 | */ 16 | export declare function hashTransaction(serializedTx: Uint8Array): Uint8Array; 17 | /** 18 | * Parses the NEAR public key from its string representation. 19 | * @param mpcPublicKey - The NEAR-formatted public key string. 20 | * @returns The decoded public key bytes. 21 | */ 22 | export declare function parsePublicKey(mpcPublicKey: string): Buffer; 23 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/cryptoUtils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // cryptoUtils.ts 3 | var __importDefault = (this && this.__importDefault) || function (mod) { 4 | return (mod && mod.__esModule) ? mod : { "default": mod }; 5 | }; 6 | Object.defineProperty(exports, "__esModule", { value: true }); 7 | exports.parsePublicKey = exports.hashTransaction = exports.createSignature = void 0; 8 | const bs58_1 = __importDefault(require("bs58")); 9 | const js_sha256_1 = require("js-sha256"); 10 | const transaction_1 = require("near-api-js/lib/transaction"); 11 | const key_pair_1 = require("near-api-js/lib/utils/key_pair"); 12 | /** 13 | * Creates a NEAR Signature object from r, s, and recovery ID. 14 | * @param r - The r component of the signature. 15 | * @param s - The s component of the signature. 16 | * @returns A NEAR Signature object. 17 | */ 18 | function createSignature(r, s) { 19 | return new transaction_1.Signature({ 20 | keyType: key_pair_1.KeyType.SECP256K1, 21 | data: Buffer.concat([ 22 | Buffer.from(r.substring(2), "hex"), 23 | Buffer.from(s, "hex"), 24 | Buffer.from(r.substring(0, 2), "hex"), 25 | ]), 26 | }); 27 | } 28 | exports.createSignature = createSignature; 29 | /** 30 | * Hashes the serialized transaction using SHA-256. 31 | * @param serializedTx - The serialized transaction bytes. 32 | * @returns The SHA-256 hash as a Uint8Array. 33 | */ 34 | function hashTransaction(serializedTx) { 35 | return new Uint8Array(js_sha256_1.sha256.array(serializedTx)); 36 | } 37 | exports.hashTransaction = hashTransaction; 38 | /** 39 | * Parses the NEAR public key from its string representation. 40 | * @param mpcPublicKey - The NEAR-formatted public key string. 41 | * @returns The decoded public key bytes. 42 | */ 43 | function parsePublicKey(mpcPublicKey) { 44 | // Remove 'secp256k1:' prefix and decode 45 | const publicKeyBytes = bs58_1.default.decode(mpcPublicKey.replace("secp256k1:", "")); 46 | return Buffer.from(publicKeyBytes); 47 | } 48 | exports.parsePublicKey = parsePublicKey; 49 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/evmUtils.d.ts: -------------------------------------------------------------------------------- 1 | import { JsonRpcProvider, VoidSigner } from "ethers"; 2 | import { ActionToPerform } from "./types"; 3 | import { SerializableParam, SerializableToken } from "./types/EVMTypes"; 4 | export declare function esimateGasParams(provider: JsonRpcProvider, signer: VoidSigner, actionToPerform: ActionToPerform): Promise<{ 5 | nonce: number; 6 | gasLimit: bigint; 7 | maxFeePerGas: bigint; 8 | maxPriorityFeePerGas: bigint; 9 | }>; 10 | /** 11 | * Converts method name and arguments into SerializableParam[] and SerializableToken[]. 12 | * @param methodName - The name of the method. 13 | * @param args - The arguments to the method. 14 | * @param abi - The ABI of the contract. 15 | * @returns An object containing methodParams and args in the required formats. 16 | */ 17 | export declare function encodeMethodParams(methodName: string, args: any[] | Record, abi: any[]): { 18 | methodParams: SerializableParam[]; 19 | args: SerializableToken[]; 20 | }; 21 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/logUtils.d.ts: -------------------------------------------------------------------------------- 1 | export declare const RED = "\u001B[31m"; 2 | /** 3 | * Logs a success message in green. 4 | * @param message - The message to log. 5 | */ 6 | export declare function logSuccess(message: string): void; 7 | /** 8 | * Logs an error message in red. 9 | * @param message - The message to log. 10 | */ 11 | export declare function logError(message: string): void; 12 | /** 13 | * Logs an informational message in blue. 14 | * @param message - The message to log. 15 | */ 16 | export declare function logInfo(message: string): void; 17 | /** 18 | * Extracts logs from the transaction result. 19 | * @param result - The transaction result object. 20 | * @returns An array of log strings. 21 | */ 22 | export declare function extractLogsFromResult(result: any): string[]; 23 | export declare function parseContractLog(log: string): any; 24 | /** 25 | * Parses the Actions string from a contract log. 26 | * @param actionsStr - The Actions string to parse. 27 | * @returns An array of parsed action objects. 28 | */ 29 | export declare function parseActionsString(actionsStr: string): any[]; 30 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/mpcUtils/kdf.d.ts: -------------------------------------------------------------------------------- 1 | export declare function najPublicKeyStrToUncompressedHexPoint(najPublicKeyStr: string): string; 2 | export declare function deriveChildPublicKey(parentUncompressedPublicKeyHex: string, signerId: string, path?: string): string; 3 | export declare function uncompressedHexPointToEvmAddress(uncompressedHexPoint: string): string; 4 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/mpcUtils/kdf.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.uncompressedHexPointToEvmAddress = exports.deriveChildPublicKey = exports.najPublicKeyStrToUncompressedHexPoint = void 0; 4 | const js_sha3_1 = require("js-sha3"); 5 | const elliptic_1 = require("elliptic"); 6 | const ethers_1 = require("ethers"); 7 | const serialize_1 = require("near-api-js/lib/utils/serialize"); 8 | function najPublicKeyStrToUncompressedHexPoint(najPublicKeyStr) { 9 | const decodedKey = (0, serialize_1.base_decode)(najPublicKeyStr.split(":")[1]); 10 | return "04" + Buffer.from(decodedKey).toString("hex"); 11 | } 12 | exports.najPublicKeyStrToUncompressedHexPoint = najPublicKeyStrToUncompressedHexPoint; 13 | function deriveChildPublicKey(parentUncompressedPublicKeyHex, signerId, path = "") { 14 | const ec = new elliptic_1.ec("secp256k1"); 15 | const scalarHex = (0, js_sha3_1.sha3_256)(`near-mpc-recovery v0.1.0 epsilon derivation:${signerId},${path}`); 16 | const x = parentUncompressedPublicKeyHex.substring(2, 66); 17 | const y = parentUncompressedPublicKeyHex.substring(66); 18 | // Create a point object from X and Y coordinates 19 | const oldPublicKeyPoint = ec.curve.point(x, y); 20 | // Multiply the scalar by the generator point G 21 | const scalarTimesG = ec.g.mul(scalarHex); 22 | // Add the result to the old public key point 23 | const newPublicKeyPoint = oldPublicKeyPoint.add(scalarTimesG); 24 | const newX = newPublicKeyPoint.getX().toString("hex").padStart(64, "0"); 25 | const newY = newPublicKeyPoint.getY().toString("hex").padStart(64, "0"); 26 | return "04" + newX + newY; 27 | } 28 | exports.deriveChildPublicKey = deriveChildPublicKey; 29 | function uncompressedHexPointToEvmAddress(uncompressedHexPoint) { 30 | const addressHash = (0, ethers_1.keccak256)(`0x${uncompressedHexPoint.slice(2)}`); 31 | // Ethereum address is last 20 bytes of hash (40 characters), prefixed with 0x 32 | return "0x" + addressHash.substring(addressHash.length - 40); 33 | } 34 | exports.uncompressedHexPointToEvmAddress = uncompressedHexPointToEvmAddress; 35 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/networks/near.d.ts: -------------------------------------------------------------------------------- 1 | import { SigningAccount } from "../TrialAccountManager"; 2 | import { FinalExecutionOutcome } from "@near-wallet-selector/core"; 3 | export declare function sendTransaction({ signerAccount, receiverId, methodName, args, deposit, gas, }: { 4 | signerAccount: SigningAccount; 5 | receiverId: string; 6 | methodName: string; 7 | args: any; 8 | deposit: string; 9 | gas: string; 10 | }): Promise; 11 | export declare function isFinalExecutionOutcome(result: any): result is FinalExecutionOutcome; 12 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/performAction.d.ts: -------------------------------------------------------------------------------- 1 | import { ActionToPerform, MPCSignature, TrialAccountInfo } from "./types"; 2 | import { Near } from "near-api-js"; 3 | export interface TransactionData { 4 | nonce: string; 5 | maxFeePerGas?: string; 6 | maxPriorityFeePerGas?: string; 7 | gasLimit?: string; 8 | blockHash?: string; 9 | } 10 | interface PerformActionsParams { 11 | near: Near; 12 | trialAccountInfo: TrialAccountInfo; 13 | actionsToPerform: ActionToPerform[]; 14 | evmProviderUrl?: string; 15 | } 16 | /** 17 | * Performs one or more actions by requesting signatures from the MPC. 18 | * 19 | * @param params - The parameters required to perform actions. 20 | * @returns A Promise that resolves to an array of signature arrays. 21 | */ 22 | export declare function generateActionArgs(params: PerformActionsParams): Promise<{ 23 | txnDatas: TransactionData[]; 24 | txnArgs: any[]; 25 | }>; 26 | export declare function extractSignatureFromResult(result: any): MPCSignature; 27 | export {}; 28 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/ActionToPerform.d.ts: -------------------------------------------------------------------------------- 1 | import { AccessList } from "./EVMTypes"; 2 | export interface ActionToPerform { 3 | chain: ChainType; 4 | methodName: string; 5 | args?: any[] | Record; 6 | abi?: any[]; 7 | value?: string; 8 | chainId?: number; 9 | accessList?: AccessList; 10 | targetContractId: string; 11 | attachedDepositNear?: string; 12 | gas?: string; 13 | } 14 | export type ChainType = "NEAR" | "EVM"; 15 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/ActionToPerform.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // lib/types/ActionToPerform.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/BigInts.d.ts: -------------------------------------------------------------------------------- 1 | export declare const BIGINT_27: bigint; 2 | export type PrefixedHexString = `0x${string}`; 3 | /** 4 | * Converts a {@link Uint8Array} to a {@link bigint} 5 | * @param {Uint8Array} bytes the bytes to convert 6 | * @returns {bigint} 7 | */ 8 | export declare const bytesToBigInt: (bytes: Uint8Array, littleEndian?: boolean) => bigint; 9 | export declare const bytesToHex: (bytes: Uint8Array) => PrefixedHexString; 10 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/BigInts.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.bytesToHex = exports.bytesToBigInt = exports.BIGINT_27 = void 0; 4 | exports.BIGINT_27 = BigInt(27); 5 | const BIGINT_0 = BigInt(0); 6 | /** 7 | * Converts a {@link Uint8Array} to a {@link bigint} 8 | * @param {Uint8Array} bytes the bytes to convert 9 | * @returns {bigint} 10 | */ 11 | const bytesToBigInt = (bytes, littleEndian = false) => { 12 | if (littleEndian) { 13 | bytes.reverse(); 14 | } 15 | const hex = (0, exports.bytesToHex)(bytes); 16 | if (hex === "0x") { 17 | return BIGINT_0; 18 | } 19 | if (hex.length === 4) { 20 | // If the byte length is 1 (this is faster than checking `bytes.length === 1`) 21 | return BIGINT_CACHE[bytes[0]]; 22 | } 23 | if (hex.length === 6) { 24 | return BIGINT_CACHE[bytes[0] * 256 + bytes[1]]; 25 | } 26 | return BigInt(hex); 27 | }; 28 | exports.bytesToBigInt = bytesToBigInt; 29 | /**************** Borrowed from @chainsafe/ssz */ 30 | // Caching this info costs about ~1000 bytes and speeds up toHexString() by x6 31 | const hexByByte = Array.from({ length: 256 }, (_v, i) => i.toString(16).padStart(2, "0")); 32 | const bytesToHex = (bytes) => { 33 | let hex = `0x`; 34 | if (bytes === undefined || bytes.length === 0) 35 | return hex; 36 | for (const byte of bytes) { 37 | hex = `${hex}${hexByByte[byte]}`; 38 | } 39 | return hex; 40 | }; 41 | exports.bytesToHex = bytesToHex; 42 | // BigInt cache for the numbers 0 - 256*256-1 (two-byte bytes) 43 | const BIGINT_CACHE = []; 44 | for (let i = 0; i <= 256 * 256 - 1; i++) { 45 | BIGINT_CACHE[i] = BigInt(i); 46 | } 47 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/Chain.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enum representing supported blockchains. 3 | */ 4 | export declare enum Chain { 5 | NEAR = "NEAR", 6 | Ethereum = "Ethereum" 7 | } 8 | export type ChainId = { 9 | type: "NEAR"; 10 | } | { 11 | type: "EVM"; 12 | value: number; 13 | }; 14 | export declare function serializeChainId(chainId: ChainId): any; 15 | export declare function deserializeChainId(data: any): ChainId; 16 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/Chain.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.deserializeChainId = exports.serializeChainId = exports.Chain = void 0; 4 | /** 5 | * Enum representing supported blockchains. 6 | */ 7 | var Chain; 8 | (function (Chain) { 9 | Chain["NEAR"] = "NEAR"; 10 | Chain["Ethereum"] = "Ethereum"; 11 | })(Chain = exports.Chain || (exports.Chain = {})); 12 | function serializeChainId(chainId) { 13 | if (chainId.type === "NEAR") { 14 | return { type: "NEAR" }; 15 | } 16 | else if (chainId.type === "EVM") { 17 | return { type: "EVM", value: chainId.value }; 18 | } 19 | else { 20 | throw new Error("Invalid ChainId"); 21 | } 22 | } 23 | exports.serializeChainId = serializeChainId; 24 | function deserializeChainId(data) { 25 | if (data.type === "NEAR") { 26 | return { type: "NEAR" }; 27 | } 28 | else if (data.type === "EVM") { 29 | return { type: "EVM", value: data.value }; 30 | } 31 | else { 32 | throw new Error("Invalid ChainId data"); 33 | } 34 | } 35 | exports.deserializeChainId = deserializeChainId; 36 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/ChainConstraints.d.ts: -------------------------------------------------------------------------------- 1 | export type ExtChainConstraints = { 2 | NEAR: NEARConstraints; 3 | } | { 4 | EVM: ExtEVMConstraints; 5 | }; 6 | export interface NEARConstraints { 7 | allowedMethods: string[]; 8 | allowedContracts: string[]; 9 | maxGas: string | null; 10 | maxDeposit: string | null; 11 | initialDeposit: string; 12 | } 13 | export interface ExtEVMConstraints { 14 | chainId: number; 15 | allowedMethods: string[]; 16 | allowedContracts: string[]; 17 | maxGas: number | null; 18 | maxValue: string | null; 19 | initialDeposit: bigint; 20 | } 21 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/ChainConstraints.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // lib/types/ChainConstraints.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/Constraints.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Specifies usage constraints like max contracts and methods. 3 | */ 4 | export interface UsageConstraints { 5 | maxContracts?: number; 6 | maxMethods?: number; 7 | maxTokenTransfer?: string; 8 | rateLimitPerMinute?: number; 9 | blacklistedAddresses: string[]; 10 | } 11 | /** 12 | * Defines interaction limits for trial accounts. 13 | */ 14 | export interface InteractionLimits { 15 | maxInteractionsPerDay?: number; 16 | totalInteractions?: number; 17 | } 18 | /** 19 | * Represents a function success condition based on output. 20 | */ 21 | export interface FunctionSuccessCondition { 22 | contractId: string; 23 | methodName: string; 24 | expectedReturn: string; 25 | } 26 | /** 27 | * Conditions under which the trial account will exit. 28 | */ 29 | export interface ExitConditions { 30 | transactionLimit?: number; 31 | successCondition?: FunctionSuccessCondition; 32 | timeLimit?: number; 33 | } 34 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/Constraints.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // lib/types/Constraints.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/EVMTypes.d.ts: -------------------------------------------------------------------------------- 1 | export interface SerializableParam { 2 | name: string; 3 | kind: SerializableParamType; 4 | } 5 | export type SerializableParamType = { 6 | type: "Address"; 7 | } | { 8 | type: "Bytes"; 9 | } | { 10 | type: "Int"; 11 | value: number; 12 | } | { 13 | type: "Uint"; 14 | value: number; 15 | } | { 16 | type: "Bool"; 17 | } | { 18 | type: "String"; 19 | } | { 20 | type: "Array"; 21 | value: SerializableParamType; 22 | } | { 23 | type: "FixedBytes"; 24 | value: number; 25 | } | { 26 | type: "FixedArray"; 27 | value: { 28 | inner: SerializableParamType; 29 | size: number; 30 | }; 31 | } | { 32 | type: "Tuple"; 33 | value: SerializableParamType[]; 34 | }; 35 | export type SerializableToken = { 36 | type: "Address"; 37 | value: string; 38 | } | { 39 | type: "FixedBytes"; 40 | value: string; 41 | } | { 42 | type: "Bytes"; 43 | value: string; 44 | } | { 45 | type: "Int"; 46 | value: string; 47 | } | { 48 | type: "Uint"; 49 | value: string; 50 | } | { 51 | type: "Bool"; 52 | value: boolean; 53 | } | { 54 | type: "String"; 55 | value: string; 56 | } | { 57 | type: "FixedArray"; 58 | value: SerializableToken[]; 59 | } | { 60 | type: "Array"; 61 | value: SerializableToken[]; 62 | } | { 63 | type: "Tuple"; 64 | value: SerializableToken[]; 65 | }; 66 | export interface AccessListItem { 67 | address: string; 68 | storageKeys: string[]; 69 | } 70 | export type AccessList = AccessListItem[]; 71 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/EVMTypes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // lib/types/EVMTypes.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/KeyData.d.ts: -------------------------------------------------------------------------------- 1 | import { KeyPairString } from "near-api-js/lib/utils"; 2 | /** 3 | * Key data structure containing information about a trial key. 4 | */ 5 | export interface KeyData { 6 | publicKey: string; 7 | secretKey: string; 8 | trialId: number; 9 | mpcKey: string; 10 | } 11 | /** 12 | * Represents a trial key along with its associated account ID and MPC key. 13 | */ 14 | export interface TrialKey { 15 | derivationPath: string; 16 | trialAccountSecretKey: KeyPairString; 17 | trialAccountPublicKey: string; 18 | mpcKey: string; 19 | } 20 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/KeyData.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/KeyUsage.d.ts: -------------------------------------------------------------------------------- 1 | import { AccountIdByChainId, UsageStats } from "./TrialAccountInfo"; 2 | /** 3 | * Associates a public key with its usage stats and trial ID. 4 | */ 5 | export interface KeyUsage { 6 | trialId: number; 7 | mpcKey: string; 8 | accountId: AccountIdByChainId; 9 | usageStats: UsageStats; 10 | } 11 | /** 12 | * Structure representing a key with both a public key and MPC key. 13 | */ 14 | export interface KeyWithMPC { 15 | publicKey: string; 16 | mpcKey: string; 17 | } 18 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/KeyUsage.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/MPCSignature.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Result Type of MPC contract signature request. 3 | * Representing Affine Points on eliptic curve. 4 | * Example: { 5 | "big_r": { 6 | "affine_point": "031F2CE94AF69DF45EC96D146DB2F6D35B8743FA2E21D2450070C5C339A4CD418B" 7 | }, 8 | "s": { "scalar": "5AE93A7C4138972B3FE8AEA1638190905C6DB5437BDE7274BEBFA41DDAF7E4F6" 9 | }, 10 | "recovery_id": 0 11 | } 12 | */ 13 | export interface MPCSignature { 14 | big_r: { 15 | affine_point: string; 16 | }; 17 | s: { 18 | scalar: string; 19 | }; 20 | recovery_id: number; 21 | } 22 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/MPCSignature.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * Result Type of MPC contract signature request. 4 | * Representing Affine Points on eliptic curve. 5 | * Example: { 6 | "big_r": { 7 | "affine_point": "031F2CE94AF69DF45EC96D146DB2F6D35B8743FA2E21D2450070C5C339A4CD418B" 8 | }, 9 | "s": { "scalar": "5AE93A7C4138972B3FE8AEA1638190905C6DB5437BDE7274BEBFA41DDAF7E4F6" 10 | }, 11 | "recovery_id": 0 12 | } 13 | */ 14 | Object.defineProperty(exports, "__esModule", { value: true }); 15 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/TrialAccountInfo.d.ts: -------------------------------------------------------------------------------- 1 | import { TrialData } from "./TrialData"; 2 | /** 3 | * Usage statistics for the trial account. 4 | */ 5 | export interface UsageStats { 6 | interactionsPerDay: { 7 | [timestamp: number]: number; 8 | }; 9 | totalInteractions: number; 10 | methodsCalled: { 11 | [methodName: string]: number; 12 | }; 13 | contractsCalled: { 14 | [contractId: string]: number; 15 | }; 16 | gasUsed: string; 17 | depositUsed: string; 18 | } 19 | /** 20 | * Represents usage stats and account information for a trial account. 21 | */ 22 | export interface TrialAccountInfo { 23 | trialId: number; 24 | trialData: TrialData; 25 | mpcKey: string; 26 | accountIdByChainId: AccountIdByChainId; 27 | usageStats: UsageStats; 28 | } 29 | export type AccountIdByChainId = Record; 30 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/TrialAccountInfo.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // lib/types/TrialAccountInfo.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/TrialData.d.ts: -------------------------------------------------------------------------------- 1 | import { UsageConstraints, InteractionLimits, ExitConditions } from "./Constraints"; 2 | import { ExtEVMConstraints, NEARConstraints } from "./ChainConstraints"; 3 | /** 4 | * Data required to create a trial. 5 | */ 6 | export interface TrialData { 7 | constraintsByChainId: { 8 | NEAR?: NEARConstraints; 9 | EVM?: ExtEVMConstraints; 10 | }; 11 | usageConstraints: UsageConstraints | null; 12 | interactionLimits: InteractionLimits | null; 13 | exitConditions: ExitConditions | null; 14 | expirationTime: number | null; 15 | creatorAccountId?: string; 16 | } 17 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/TrialData.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // lib/types/TrialData.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from "./BigInts"; 2 | export * from "./EVMTypes"; 3 | export * from "./TrialAccountInfo"; 4 | export * from "./Constraints"; 5 | export * from "./ActionToPerform"; 6 | export * from "./TrialData"; 7 | export * from "./KeyData"; 8 | export * from "./MPCSignature"; 9 | export * from "./Chain"; 10 | export * from "./KeyUsage"; 11 | export * from "./util"; 12 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // lib/types/index.ts 3 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 4 | if (k2 === undefined) k2 = k; 5 | var desc = Object.getOwnPropertyDescriptor(m, k); 6 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 7 | desc = { enumerable: true, get: function() { return m[k]; } }; 8 | } 9 | Object.defineProperty(o, k2, desc); 10 | }) : (function(o, m, k, k2) { 11 | if (k2 === undefined) k2 = k; 12 | o[k2] = m[k]; 13 | })); 14 | var __exportStar = (this && this.__exportStar) || function(m, exports) { 15 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); 16 | }; 17 | Object.defineProperty(exports, "__esModule", { value: true }); 18 | __exportStar(require("./BigInts"), exports); 19 | __exportStar(require("./EVMTypes"), exports); 20 | __exportStar(require("./TrialAccountInfo"), exports); 21 | __exportStar(require("./Constraints"), exports); 22 | __exportStar(require("./ActionToPerform"), exports); 23 | __exportStar(require("./TrialData"), exports); 24 | __exportStar(require("./KeyData"), exports); 25 | __exportStar(require("./MPCSignature"), exports); 26 | __exportStar(require("./Chain"), exports); 27 | __exportStar(require("./KeyUsage"), exports); 28 | __exportStar(require("./util"), exports); 29 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/util.d.ts: -------------------------------------------------------------------------------- 1 | export declare function snakeToCamel(str: string): string; 2 | export declare function convertKeysToCamelCase(obj: any): any; 3 | /** 4 | * Converts an object's keys from camelCase to snake_case recursively, 5 | * but keeps all-uppercase keys unchanged. 6 | * 7 | * @param obj - The object to be converted. 8 | * @returns The new object with snake_case keys. 9 | */ 10 | export declare function toSnakeCase(obj: any): any; 11 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/types/util.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | // lib/types/util.ts 3 | Object.defineProperty(exports, "__esModule", { value: true }); 4 | exports.toSnakeCase = exports.convertKeysToCamelCase = exports.snakeToCamel = void 0; 5 | // Utility to convert a string from snake_case to camelCase 6 | function snakeToCamel(str) { 7 | return str.replace(/(_\w)/g, (m) => m[1].toUpperCase()); 8 | } 9 | exports.snakeToCamel = snakeToCamel; 10 | // Recursive function to convert all keys of an object from snake_case to camelCase 11 | function convertKeysToCamelCase(obj) { 12 | if (Array.isArray(obj)) { 13 | return obj.map((item) => convertKeysToCamelCase(item)); 14 | } 15 | else if (obj !== null && obj.constructor === Object) { 16 | return Object.keys(obj).reduce((result, key) => { 17 | const camelCaseKey = snakeToCamel(key); 18 | result[camelCaseKey] = convertKeysToCamelCase(obj[key]); 19 | return result; 20 | }, {}); 21 | } 22 | return obj; // Return if neither object nor array 23 | } 24 | exports.convertKeysToCamelCase = convertKeysToCamelCase; 25 | /** 26 | * Converts an object's keys from camelCase to snake_case recursively, 27 | * but keeps all-uppercase keys unchanged. 28 | * 29 | * @param obj - The object to be converted. 30 | * @returns The new object with snake_case keys. 31 | */ 32 | function toSnakeCase(obj) { 33 | if (Array.isArray(obj)) { 34 | return obj.map((item) => toSnakeCase(item)); 35 | } 36 | else if (obj && typeof obj === "object" && obj.constructor === Object) { 37 | return Object.keys(obj).reduce((acc, key) => { 38 | // Check if the key is all uppercase 39 | const snakeKey = /^[A-Z0-9_]+$/.test(key) 40 | ? key 41 | : key.replace(/([A-Z])/g, "_$1").toLowerCase(); 42 | acc[snakeKey] = toSnakeCase(obj[key]); 43 | return acc; 44 | }, {}); 45 | } 46 | return obj; 47 | } 48 | exports.toSnakeCase = toSnakeCase; 49 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/validityChecker.d.ts: -------------------------------------------------------------------------------- 1 | import { ActionToPerform, TrialData, UsageStats } from "./types"; 2 | import { TransactionData } from "./performAction"; 3 | /** 4 | * Checks the validity of actions against trial data constraints. 5 | * @param actionsToPerform - The actions to validate. 6 | * @param trialData - The trial data containing constraints. 7 | * @param usageStats - Current usage statistics for the trial account. 8 | * @param currentTimestamp - The current timestamp in nanoseconds. 9 | * @throws Will throw an error if any action is invalid. 10 | */ 11 | export declare function checkActionValidity(actionsToPerform: ActionToPerform[], txnDatas: TransactionData[], trialData: TrialData, usageStats: UsageStats, currentTimestamp: number): void; 12 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/wallet-selector/setup.d.ts: -------------------------------------------------------------------------------- 1 | import type { WalletModuleFactory } from "@near-wallet-selector/core"; 2 | import { KeypomWalletInstant, OneClickParams } from "./types"; 3 | export declare function setupKeypomTrialSelector(params: OneClickParams): WalletModuleFactory; 4 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/wallet-selector/types.d.ts: -------------------------------------------------------------------------------- 1 | import { InstantLinkWallet, NetworkId } from "@near-wallet-selector/core"; 2 | import { KeypomTrialSelector } from "./wallet"; 3 | export declare const FAILED_EXECUTION_OUTCOME: any; 4 | export interface SignInOptions { 5 | contractId?: string; 6 | allowance?: string; 7 | methodNames?: string[]; 8 | } 9 | export interface KeypomInitializeOptions { 10 | keypomWallet: KeypomTrialSelector; 11 | } 12 | export interface OneClickParams { 13 | networkId: NetworkId; 14 | contractId: string; 15 | allowance?: string; 16 | methodNames?: string[]; 17 | } 18 | export declare const isOneClickParams: (params: OneClickParams) => boolean; 19 | export type KeypomWalletInstant = InstantLinkWallet & { 20 | networkId: string; 21 | getContractId(): string; 22 | switchAccount(id: string): Promise; 23 | getAccountId(): string; 24 | isSignedIn: () => Promise; 25 | getAvailableBalance: () => Promise; 26 | showModal(): any; 27 | }; 28 | export type AddKeyPermission = "FullAccess" | { 29 | receiverId: string; 30 | allowance?: string; 31 | methodNames?: Array; 32 | }; 33 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/wallet-selector/types.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.isOneClickParams = exports.FAILED_EXECUTION_OUTCOME = void 0; 4 | exports.FAILED_EXECUTION_OUTCOME = { 5 | final_execution_status: "NONE", 6 | status: { 7 | Failure: { 8 | error_message: "Invalid Trial Action", 9 | error_type: "keypom-trial-error", 10 | }, 11 | }, 12 | transaction: {}, 13 | transaction_outcome: { 14 | id: "", 15 | outcome: { 16 | logs: [], 17 | receipt_ids: [], 18 | tokens_burnt: "0", 19 | executor_id: "", 20 | gas_burnt: 0, 21 | status: { 22 | Failure: { 23 | error_message: "Invalid Trial Action", 24 | error_type: "keypom-trial-error", 25 | }, 26 | }, 27 | }, 28 | }, 29 | receipts_outcome: [ 30 | { 31 | id: "", 32 | outcome: { 33 | logs: [], 34 | receipt_ids: [], 35 | gas_burnt: 0, 36 | tokens_burnt: "0", 37 | executor_id: "", 38 | status: { 39 | Failure: { 40 | error_message: "Invalid Trial Action", 41 | error_type: "keypom-trial-error", 42 | }, 43 | }, 44 | }, 45 | }, 46 | ], 47 | }; 48 | const isOneClickParams = (params) => typeof params.networkId === "string" && 49 | (params.networkId === "testnet" || params.networkId === "mainnet"); 50 | exports.isOneClickParams = isOneClickParams; 51 | -------------------------------------------------------------------------------- /packages/trial-accounts/lib/lib/wallet-selector/wallet.d.ts: -------------------------------------------------------------------------------- 1 | import { FinalExecutionOutcome, InstantLinkWalletBehaviour, Transaction, VerifiedOwner, VerifyOwnerParams } from "@near-wallet-selector/core"; 2 | import { TrialAccountManager } from "../TrialAccountManager"; 3 | import { KeyPairString } from "near-api-js/lib/utils"; 4 | export declare class KeypomTrialSelector implements InstantLinkWalletBehaviour { 5 | networkId: string; 6 | trialAccountSecretKey: KeyPairString; 7 | trialAccountId: string; 8 | trialManager: TrialAccountManager; 9 | constructor({ networkId, trialAccountSecretKey, trialAccountId, }: { 10 | networkId: string; 11 | trialAccountSecretKey: KeyPairString; 12 | trialAccountId: string; 13 | }); 14 | verifyOwner(params: VerifyOwnerParams): Promise; 15 | getContractId(): string; 16 | getAccountId(): string; 17 | isSignedIn(): boolean; 18 | signAndSendTransaction(params: any): Promise; 19 | signAndSendTransactions(params: { 20 | transactions: Transaction[]; 21 | }): Promise; 22 | signIn(): Promise<{ 23 | accountId: string; 24 | }[]>; 25 | signOut(): Promise; 26 | getAvailableBalance(): Promise; 27 | getAccounts(): Promise<{ 28 | accountId: string; 29 | }[]>; 30 | switchAccount(id: string): Promise; 31 | } 32 | -------------------------------------------------------------------------------- /packages/trial-accounts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@keypom/trial-accounts", 3 | "version": "0.1.7", 4 | "description": "Core library for interacting with and creating Multichain Trial Accounts", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "build": "pnpm compile", 8 | "compile": "tsc -p tsconfig.json", 9 | "deploy:near": "ts-node deploy/main.ts nearSimple", 10 | "deploy:evm": "ts-node deploy/main.ts evmSimple", 11 | "deploy:omni": "ts-node deploy/main.ts omniChainSimple", 12 | "debug:logs": "ts-node deploy/compareLogs.ts", 13 | "broadcast:evm": "ts-node deploy/broadcastSig.ts evmSimple", 14 | "broadcast:near": "ts-node deploy/broadcastSig.ts nearSimple", 15 | "broadcast:omni": "ts-node deploy/broadcastSig.ts omniChainSimple", 16 | "lint:js": "eslint -c ../../.eslintrc.js.yml src/**/*.js --no-eslintrc", 17 | "lint:js:fix": "eslint -c ../../.eslintrc.js.yml src/**/*.js --no-eslintrc --fix", 18 | "lint:ts": "eslint -c ../../.eslintrc.ts.yml src/**/*.ts --no-eslintrc", 19 | "lint:ts:fix": "eslint -c ../../.eslintrc.ts.yml src/**/*.ts --no-eslintrc --fix", 20 | "build-docs": "npx typedoc --options typedoc.json" 21 | }, 22 | "author": "benkurrek", 23 | "license": "MIT", 24 | "dependencies": { 25 | "@near-wallet-selector/core": "^8.9.13", 26 | "bs58": "^6.0.0", 27 | "elliptic": "^6.5.7", 28 | "ethers": "^6.13.4", 29 | "hash.js": "^1.1.7", 30 | "js-sha256": "^0.11.0", 31 | "js-sha3": "^0.9.3", 32 | "near-api-js": "^5.0.1", 33 | "tweetnacl-util": "^0.15.1" 34 | }, 35 | "ava": { 36 | "require": [ 37 | "dotenv/config" 38 | ] 39 | }, 40 | "devDependencies": { 41 | "ava": "^4.3.3", 42 | "dotenv": "^16.0.3", 43 | "eslint": "^8.39.0", 44 | "typedoc": "^0.23.24", 45 | "typescript": "^4.8.4" 46 | }, 47 | "files": [ 48 | "lib" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/index.ts: -------------------------------------------------------------------------------- 1 | // index.ts 2 | 3 | /** 4 | * Main entry point for the Trial Accounts package. 5 | * 6 | * This package provides functions to deploy trial contracts, 7 | * create trials, add trial accounts, activate trial accounts, 8 | * perform actions, and broadcast transactions. 9 | * 10 | * @packageDocumentation 11 | */ 12 | 13 | export { TrialAccountManager } from "./lib/TrialAccountManager"; 14 | export { setupKeypomTrialSelector } from "./lib/wallet-selector/setup"; 15 | 16 | // Export types for user convenience 17 | export * from "./lib/types"; 18 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/activateTrial.ts: -------------------------------------------------------------------------------- 1 | // activateTrial.ts 2 | 3 | import { Near } from "near-api-js"; 4 | import { KeyPair, KeyPairString } from "near-api-js/lib/utils"; 5 | import { sendTransaction } from "./networks/near"; 6 | 7 | interface ActivateTrialAccountsParams { 8 | near: Near; 9 | trialContractId: string; 10 | trialAccountIds: string[]; 11 | trialAccountSecretKeys: KeyPairString[]; 12 | chainIds: string[]; 13 | } 14 | 15 | /** 16 | * Activates trial accounts on the trial contract. 17 | * 18 | * @param params - The parameters required to activate trial accounts. 19 | * @returns A Promise that resolves when all accounts are activated. 20 | * @throws Will throw an error if activation of any trial account fails. 21 | */ 22 | export async function activateTrialAccounts( 23 | params: ActivateTrialAccountsParams 24 | ): Promise { 25 | const { trialContractId, trialAccountIds, near, trialAccountSecretKeys } = 26 | params; 27 | 28 | for (let i = 0; i < trialAccountIds.length; i++) { 29 | const trialAccountId = trialAccountIds[i]; 30 | const trialKey = trialAccountSecretKeys[i]; 31 | const chainId = params.chainIds[i]; 32 | 33 | // Set the trial key in the keyStore 34 | const keyStore: any = (near.connection.signer as any).keyStore; 35 | await keyStore.setKey( 36 | near.connection.networkId, 37 | trialContractId, 38 | KeyPair.fromString(trialKey) 39 | ); 40 | const signerAccount = await near.account(trialContractId); 41 | 42 | const result = await sendTransaction({ 43 | signerAccount, 44 | receiverId: trialContractId, 45 | methodName: "activate_trial", 46 | args: { 47 | new_account_id: trialAccountId, 48 | chain_id: chainId.toString(), 49 | }, 50 | deposit: "0", 51 | gas: "300000000000000", 52 | }); 53 | 54 | if (!result) { 55 | throw new Error( 56 | `Failed to activate trial account: ${trialAccountId}` 57 | ); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/addTrialKeys.ts: -------------------------------------------------------------------------------- 1 | // addTrialKeys.ts 2 | 3 | import { KeyPair } from "near-api-js"; 4 | import { TrialKey } from "./types"; 5 | 6 | interface AddTrialAccountsParams { 7 | trialContractId: string; 8 | mpcContractId: string; 9 | numberOfKeys: number; 10 | viewFunction: any; 11 | } 12 | 13 | /** 14 | * Generates the trial key data needed to add trial accounts. 15 | * 16 | * @param params - The number of keys to generate. 17 | * @returns A Promise that resolves to an array of TrialKey objects. 18 | */ 19 | export async function generateTrialKeys( 20 | params: AddTrialAccountsParams 21 | ): Promise { 22 | const { trialContractId, mpcContractId, numberOfKeys, viewFunction } = 23 | params; 24 | 25 | const trialKeys: TrialKey[] = []; 26 | 27 | for (let i = 0; i < numberOfKeys; i++) { 28 | // Generate a new key pair 29 | const keyPair = KeyPair.fromRandom("ed25519"); 30 | 31 | // Derive the MPC public key 32 | const derivationPath = keyPair.getPublicKey().toString(); 33 | 34 | const mpcPublicKey = await viewFunction({ 35 | contractId: mpcContractId, 36 | methodName: "derived_public_key", 37 | args: { 38 | path: derivationPath, 39 | predecessor: trialContractId, 40 | }, 41 | }); 42 | 43 | trialKeys.push({ 44 | derivationPath, 45 | trialAccountSecretKey: keyPair.toString(), 46 | trialAccountPublicKey: keyPair.getPublicKey().toString(), 47 | mpcKey: mpcPublicKey, 48 | }); 49 | } 50 | 51 | return trialKeys; 52 | } 53 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/createTrial.ts: -------------------------------------------------------------------------------- 1 | // lib/createTrial.ts 2 | 3 | import { toSnakeCase, TrialData } from "./types"; 4 | import { ExtEVMConstraints, NEARConstraints } from "./types/ChainConstraints"; 5 | 6 | /** 7 | * Generates the arguments for creating a trial. 8 | * 9 | * @param params - The parameters required to create a trial. 10 | * @returns A Record containing the arguments for creating a trial. 11 | */ 12 | export function getCreateTrialParams( 13 | trialData: TrialData 14 | ): Record { 15 | // Type guard to check if value is ExtEVMConstraints 16 | const isExtEVMConstraints = ( 17 | value: NEARConstraints | ExtEVMConstraints 18 | ): value is ExtEVMConstraints => { 19 | return (value as ExtEVMConstraints).chainId !== undefined; 20 | }; 21 | 22 | // Transform constraintsByChainId to use chain ID directly if it's EVM 23 | const transformedConstraints = Object.entries( 24 | trialData.constraintsByChainId 25 | ).reduce((acc, [key, value]) => { 26 | if (key === "EVM" && isExtEVMConstraints(value)) { 27 | // Now TypeScript knows that value is ExtEVMConstraints 28 | const evmConstraints = value; 29 | acc[evmConstraints.chainId] = { ...evmConstraints }; 30 | acc[evmConstraints.chainId].initialDeposit = 31 | acc[evmConstraints.chainId].initialDeposit.toString(); 32 | // @ts-ignore 33 | delete acc[evmConstraints.chainId].chainId; // Remove chainId as it's now used as the key 34 | } else { 35 | acc[key] = value; 36 | } 37 | return acc; 38 | }, {} as Record); 39 | 40 | const { constraintsByChainId, ...restTrialData } = trialData; 41 | 42 | const snakeCaseArgs = toSnakeCase({ 43 | ...restTrialData, 44 | chain_constraints: transformedConstraints, // Use transformed constraints here 45 | }); 46 | return snakeCaseArgs; 47 | } 48 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/cryptoUtils.ts: -------------------------------------------------------------------------------- 1 | // cryptoUtils.ts 2 | 3 | import bs58 from "bs58"; 4 | import { sha256 } from "js-sha256"; 5 | import { Signature } from "near-api-js/lib/transaction"; 6 | import { KeyType } from "near-api-js/lib/utils/key_pair"; 7 | 8 | /** 9 | * Creates a NEAR Signature object from r, s, and recovery ID. 10 | * @param r - The r component of the signature. 11 | * @param s - The s component of the signature. 12 | * @returns A NEAR Signature object. 13 | */ 14 | export function createSignature(r: string, s: string): Signature { 15 | return new Signature({ 16 | keyType: KeyType.SECP256K1, 17 | data: Buffer.concat([ 18 | Buffer.from(r.substring(2), "hex"), 19 | Buffer.from(s, "hex"), 20 | Buffer.from(r.substring(0, 2), "hex"), 21 | ]), 22 | }); 23 | } 24 | 25 | /** 26 | * Hashes the serialized transaction using SHA-256. 27 | * @param serializedTx - The serialized transaction bytes. 28 | * @returns The SHA-256 hash as a Uint8Array. 29 | */ 30 | export function hashTransaction(serializedTx: Uint8Array): Uint8Array { 31 | return new Uint8Array(sha256.array(serializedTx)); 32 | } 33 | 34 | /** 35 | * Parses the NEAR public key from its string representation. 36 | * @param mpcPublicKey - The NEAR-formatted public key string. 37 | * @returns The decoded public key bytes. 38 | */ 39 | export function parsePublicKey(mpcPublicKey: string): Buffer { 40 | // Remove 'secp256k1:' prefix and decode 41 | const publicKeyBytes = bs58.decode(mpcPublicKey.replace("secp256k1:", "")); 42 | return Buffer.from(publicKeyBytes); 43 | } 44 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/mpcUtils/kdf.ts: -------------------------------------------------------------------------------- 1 | import { sha3_256 } from "js-sha3"; 2 | import { ec as EC } from "elliptic"; 3 | import { keccak256 } from "ethers"; 4 | import { base_decode } from "near-api-js/lib/utils/serialize"; 5 | 6 | export function najPublicKeyStrToUncompressedHexPoint( 7 | najPublicKeyStr: string 8 | ): string { 9 | const decodedKey = base_decode(najPublicKeyStr.split(":")[1]!); 10 | return "04" + Buffer.from(decodedKey).toString("hex"); 11 | } 12 | 13 | export function deriveChildPublicKey( 14 | parentUncompressedPublicKeyHex: string, 15 | signerId: string, 16 | path: string = "" 17 | ): string { 18 | const ec = new EC("secp256k1"); 19 | const scalarHex = sha3_256( 20 | `near-mpc-recovery v0.1.0 epsilon derivation:${signerId},${path}` 21 | ); 22 | 23 | const x = parentUncompressedPublicKeyHex.substring(2, 66); 24 | const y = parentUncompressedPublicKeyHex.substring(66); 25 | 26 | // Create a point object from X and Y coordinates 27 | const oldPublicKeyPoint = ec.curve.point(x, y); 28 | 29 | // Multiply the scalar by the generator point G 30 | const scalarTimesG = ec.g.mul(scalarHex); 31 | 32 | // Add the result to the old public key point 33 | const newPublicKeyPoint = oldPublicKeyPoint.add(scalarTimesG); 34 | const newX = newPublicKeyPoint.getX().toString("hex").padStart(64, "0"); 35 | const newY = newPublicKeyPoint.getY().toString("hex").padStart(64, "0"); 36 | return "04" + newX + newY; 37 | } 38 | 39 | export function uncompressedHexPointToEvmAddress(uncompressedHexPoint: string) { 40 | const addressHash = keccak256(`0x${uncompressedHexPoint.slice(2)}`); 41 | // Ethereum address is last 20 bytes of hash (40 characters), prefixed with 0x 42 | return "0x" + addressHash.substring(addressHash.length - 40); 43 | } 44 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/mpcUtils/mockSign.ts: -------------------------------------------------------------------------------- 1 | import { Hex, Signature, toHex } from "viem"; 2 | 3 | export function fromPayload(payload: number[]): Hex { 4 | if (payload.length !== 32) { 5 | throw new Error(`Payload must have 32 bytes: ${payload}`); 6 | } 7 | // Convert number[] back to Uint8Array 8 | return toHex(new Uint8Array(payload)); 9 | } 10 | 11 | /** 12 | * Converts a raw hexadecimal signature into a structured Signature object 13 | * @param hexSignature The raw hexadecimal signature (e.g., '0x...') 14 | * @returns A structured Signature object with fields r, s, v, and yParity 15 | */ 16 | export function hexToSignature(hexSignature: Hex): Signature { 17 | // Strip "0x" prefix if it exists 18 | const cleanedHex = hexSignature.slice(2); 19 | 20 | // Ensure the signature is 65 bytes (130 hex characters) 21 | if (cleanedHex.length !== 130) { 22 | throw new Error( 23 | `Invalid hex signature length: ${cleanedHex.length}. Expected 130 characters (65 bytes).` 24 | ); 25 | } 26 | 27 | // Extract the r, s, and v components from the hex signature 28 | const v = BigInt(`0x${cleanedHex.slice(128, 130)}`); // Last byte (2 hex characters) 29 | return { 30 | r: `0x${cleanedHex.slice(0, 64)}`, // First 32 bytes (64 hex characters) 31 | s: `0x${cleanedHex.slice(64, 128)}`, // Next 32 bytes (64 hex characters), 32 | v, 33 | // Determine yParity based on v (27 or 28 maps to 0 or 1) 34 | yParity: v === 27n ? 0 : v === 28n ? 1 : undefined, 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/mpcUtils/utils.ts: -------------------------------------------------------------------------------- 1 | export * from "./request"; 2 | export * from "./signature"; 3 | export * from "./transaction"; 4 | 5 | export { mockAdapter } from "./mock-sign"; 6 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/networks/evm.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Hash, 3 | Hex, 4 | keccak256, 5 | parseTransaction, 6 | serializeTransaction, 7 | } from "viem"; 8 | import { Network } from "."; 9 | import { TransactionWithSignature } from "./types"; 10 | 11 | export function addSignature({ 12 | transaction, 13 | signature, 14 | }: TransactionWithSignature): Hex { 15 | // @ts-ignore 16 | const txData = parseTransaction(transaction); 17 | const signedTx = { 18 | ...signature, 19 | ...txData, 20 | }; 21 | // @ts-ignore 22 | return serializeTransaction(signedTx); 23 | } 24 | 25 | /** 26 | * Relays valid representation of signed transaction to Etherem mempool for execution. 27 | * 28 | * @param {TransactionWithSignature} tx - Signed Ethereum transaction. 29 | * @returns Hash of relayed transaction. 30 | */ 31 | export async function broadcastSignedTransaction( 32 | tx: TransactionWithSignature 33 | ): Promise { 34 | const signedTx = addSignature(tx); 35 | return relaySignedTransaction(signedTx); 36 | } 37 | 38 | /** 39 | * Relays signed transaction to Ethereum mem-pool for execution. 40 | * @param serializedTransaction - Signed Ethereum transaction. 41 | * @returns Transaction Hash of relayed transaction. 42 | */ 43 | export async function relaySignedTransaction( 44 | serializedTransaction: Hex, 45 | wait: boolean = true 46 | ): Promise { 47 | // @ts-ignore 48 | const tx = parseTransaction(serializedTransaction); 49 | const network = Network.fromChainId(tx.chainId!); 50 | if (wait) { 51 | // @ts-ignore 52 | const hash = await network.client.sendRawTransaction({ 53 | serializedTransaction, 54 | }); 55 | console.log(`Transaction Confirmed: ${network.scanUrl}/tx/${hash}`); 56 | return hash; 57 | } else { 58 | // @ts-ignore 59 | network.client.sendRawTransaction({ 60 | serializedTransaction, 61 | }); 62 | return keccak256(serializedTransaction); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/networks/index.ts: -------------------------------------------------------------------------------- 1 | // from https://github.com/BitteProtocol/near-ca/blob/main/src/network/index.ts 2 | // 3 | import { createPublicClient, http, PublicClient } from "viem"; 4 | import * as chains from "viem/chains"; 5 | import { CHAIN_INFO } from "./constants"; 6 | 7 | // We support all networks exported by viem 8 | const SUPPORTED_NETWORKS = createNetworkMap(Object.values(chains)); 9 | 10 | export interface NetworkFields { 11 | name: string; 12 | rpcUrl: string; 13 | chainId: number; 14 | scanUrl: string; 15 | icon: string | undefined; 16 | testnet: boolean; 17 | nativeCurrency: { 18 | decimals: number; 19 | name: string; 20 | symbol: string; 21 | wrappedAddress: string | undefined; 22 | // This is often Network logo, but sometimes not (e.g. Gnosis Chain & xDai) 23 | icon: string | undefined; 24 | }; 25 | } 26 | /** 27 | * Leveraging Network Data provided from through viem 28 | * This class makes all relevant network fields accessible dynamically by chain ID. 29 | */ 30 | export class Network implements NetworkFields { 31 | name: string; 32 | rpcUrl: string; 33 | chainId: number; 34 | scanUrl: string; 35 | client: PublicClient; 36 | icon: string | undefined; 37 | testnet: boolean; 38 | nativeCurrency: { 39 | decimals: number; 40 | name: string; 41 | symbol: string; 42 | wrappedAddress: string | undefined; 43 | icon: string | undefined; 44 | }; 45 | 46 | constructor({ 47 | name, 48 | rpcUrl, 49 | chainId, 50 | scanUrl, 51 | nativeCurrency, 52 | icon, 53 | }: NetworkFields) { 54 | const network = SUPPORTED_NETWORKS[chainId]!; 55 | 56 | this.name = name; 57 | this.rpcUrl = rpcUrl; 58 | this.chainId = chainId; 59 | this.scanUrl = scanUrl; 60 | this.client = createPublicClient({ 61 | transport: http(network.rpcUrl), 62 | }); 63 | this.testnet = network.testnet; 64 | this.nativeCurrency = nativeCurrency; 65 | this.icon = icon; 66 | } 67 | 68 | static fromChainId(chainId: number): Network { 69 | const networkFields = SUPPORTED_NETWORKS[chainId]; 70 | if (!networkFields) { 71 | throw new Error( 72 | `Network with chainId ${chainId} is not supported. 73 | Please reach out to the developers of https://github.com/Mintbase/near-ca` 74 | ); 75 | } 76 | return new Network(networkFields); 77 | } 78 | } 79 | 80 | type NetworkMap = { [key: number]: NetworkFields }; 81 | 82 | /// Dynamically generate network map accessible by chainId. 83 | function createNetworkMap(supportedNetworks: any): NetworkMap { 84 | const networkMap: NetworkMap = {}; 85 | supportedNetworks.forEach((network) => { 86 | const chainInfo = CHAIN_INFO[network.id]; 87 | const icon = chainInfo?.icon || `/${network.nativeCurrency.symbol}.svg`; 88 | networkMap[network.id] = { 89 | name: network.name, 90 | rpcUrl: network.rpcUrls.default.http[0]!, 91 | chainId: network.id, 92 | scanUrl: network.blockExplorers?.default.url || "", 93 | icon, 94 | testnet: network.testnet || false, 95 | nativeCurrency: { 96 | ...network.nativeCurrency, 97 | wrappedAddress: chainInfo?.wrappedToken, 98 | icon: chainInfo?.currencyIcon || icon, 99 | }, 100 | }; 101 | }); 102 | 103 | return networkMap; 104 | } 105 | 106 | export function isTestnet(chainId: number): boolean { 107 | return Network.fromChainId(chainId).testnet; 108 | } 109 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/ActionToPerform.ts: -------------------------------------------------------------------------------- 1 | // lib/types/ActionToPerform.ts 2 | 3 | import { AccessList } from "./EVMTypes"; 4 | 5 | export interface ActionToPerform { 6 | chain: ChainType; 7 | methodName: string; 8 | args?: any[] | Record; // Simplify args input 9 | abi?: any[]; // Optionally provide ABI 10 | value?: string; // For EVM, represented as a string 11 | chainId?: number; // For EVM, represented as a number 12 | accessList?: AccessList; // Updated type 13 | targetContractId: string; // For EVM, this would be the contract address 14 | attachedDepositNear?: string; // For NEAR, represented as a string 15 | gas?: string; // For NEAR, represented as a string 16 | } 17 | 18 | export type ChainType = "NEAR" | "EVM"; 19 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/BigInts.ts: -------------------------------------------------------------------------------- 1 | export const BIGINT_27 = BigInt(27); 2 | const BIGINT_0 = BigInt(0); 3 | 4 | /* 5 | * A type that represents a `0x`-prefixed hex string. 6 | */ 7 | export type PrefixedHexString = `0x${string}`; 8 | 9 | /** 10 | * Converts a {@link Uint8Array} to a {@link bigint} 11 | * @param {Uint8Array} bytes the bytes to convert 12 | * @returns {bigint} 13 | */ 14 | export const bytesToBigInt = ( 15 | bytes: Uint8Array, 16 | littleEndian = false 17 | ): bigint => { 18 | if (littleEndian) { 19 | bytes.reverse(); 20 | } 21 | const hex = bytesToHex(bytes); 22 | if (hex === "0x") { 23 | return BIGINT_0; 24 | } 25 | if (hex.length === 4) { 26 | // If the byte length is 1 (this is faster than checking `bytes.length === 1`) 27 | return BIGINT_CACHE[bytes[0]]; 28 | } 29 | if (hex.length === 6) { 30 | return BIGINT_CACHE[bytes[0] * 256 + bytes[1]]; 31 | } 32 | return BigInt(hex); 33 | }; 34 | 35 | /**************** Borrowed from @chainsafe/ssz */ 36 | // Caching this info costs about ~1000 bytes and speeds up toHexString() by x6 37 | const hexByByte = Array.from({ length: 256 }, (_v, i) => 38 | i.toString(16).padStart(2, "0") 39 | ); 40 | 41 | export const bytesToHex = (bytes: Uint8Array): PrefixedHexString => { 42 | let hex: PrefixedHexString = `0x`; 43 | if (bytes === undefined || bytes.length === 0) return hex; 44 | for (const byte of bytes) { 45 | hex = `${hex}${hexByByte[byte]}`; 46 | } 47 | return hex; 48 | }; 49 | 50 | // BigInt cache for the numbers 0 - 256*256-1 (two-byte bytes) 51 | const BIGINT_CACHE: bigint[] = []; 52 | for (let i = 0; i <= 256 * 256 - 1; i++) { 53 | BIGINT_CACHE[i] = BigInt(i); 54 | } 55 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/Chain.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Enum representing supported blockchains. 3 | */ 4 | export enum Chain { 5 | NEAR = "NEAR", 6 | Ethereum = "Ethereum", 7 | } 8 | 9 | export type ChainId = { type: "NEAR" } | { type: "EVM"; value: number }; 10 | 11 | export function serializeChainId(chainId: ChainId): any { 12 | if (chainId.type === "NEAR") { 13 | return { type: "NEAR" }; 14 | } else if (chainId.type === "EVM") { 15 | return { type: "EVM", value: chainId.value }; 16 | } else { 17 | throw new Error("Invalid ChainId"); 18 | } 19 | } 20 | 21 | export function deserializeChainId(data: any): ChainId { 22 | if (data.type === "NEAR") { 23 | return { type: "NEAR" }; 24 | } else if (data.type === "EVM") { 25 | return { type: "EVM", value: data.value }; 26 | } else { 27 | throw new Error("Invalid ChainId data"); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/ChainConstraints.ts: -------------------------------------------------------------------------------- 1 | // lib/types/ChainConstraints.ts 2 | 3 | export type ExtChainConstraints = 4 | | { NEAR: NEARConstraints } 5 | | { EVM: ExtEVMConstraints }; 6 | 7 | export interface NEARConstraints { 8 | allowedMethods: string[]; 9 | allowedContracts: string[]; 10 | maxGas: string | null; 11 | maxDeposit: string | null; 12 | initialDeposit: string; 13 | } 14 | 15 | export interface ExtEVMConstraints { 16 | chainId: number; 17 | allowedMethods: string[]; 18 | allowedContracts: string[]; 19 | maxGas: number | null; 20 | maxValue: string | null; 21 | initialDeposit: bigint; 22 | } 23 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/Constraints.ts: -------------------------------------------------------------------------------- 1 | // lib/types/Constraints.ts 2 | 3 | /** 4 | * Specifies usage constraints like max contracts and methods. 5 | */ 6 | export interface UsageConstraints { 7 | maxContracts?: number; 8 | maxMethods?: number; 9 | maxTokenTransfer?: string; // U128 represented as a string 10 | rateLimitPerMinute?: number; 11 | blacklistedAddresses: string[]; // Use string to represent addresses for both NEAR and EVM 12 | } 13 | 14 | /** 15 | * Defines interaction limits for trial accounts. 16 | */ 17 | export interface InteractionLimits { 18 | maxInteractionsPerDay?: number; 19 | totalInteractions?: number; 20 | } 21 | 22 | /** 23 | * Represents a function success condition based on output. 24 | */ 25 | export interface FunctionSuccessCondition { 26 | contractId: string; 27 | methodName: string; 28 | expectedReturn: string; 29 | } 30 | 31 | /** 32 | * Conditions under which the trial account will exit. 33 | */ 34 | export interface ExitConditions { 35 | transactionLimit?: number; 36 | successCondition?: FunctionSuccessCondition; 37 | timeLimit?: number; // Timestamp in nanoseconds 38 | } 39 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/EVMTypes.ts: -------------------------------------------------------------------------------- 1 | // lib/types/EVMTypes.ts 2 | 3 | export interface SerializableParam { 4 | name: string; 5 | kind: SerializableParamType; 6 | } 7 | 8 | export type SerializableParamType = 9 | | { type: "Address" } 10 | | { type: "Bytes" } 11 | | { type: "Int"; value: number } 12 | | { type: "Uint"; value: number } 13 | | { type: "Bool" } 14 | | { type: "String" } 15 | | { type: "Array"; value: SerializableParamType } 16 | | { type: "FixedBytes"; value: number } 17 | | { 18 | type: "FixedArray"; 19 | value: { inner: SerializableParamType; size: number }; 20 | } 21 | | { type: "Tuple"; value: SerializableParamType[] }; 22 | 23 | export type SerializableToken = 24 | | { type: "Address"; value: string } // address as hex string 25 | | { type: "FixedBytes"; value: string } // hex string 26 | | { type: "Bytes"; value: string } // hex string 27 | | { type: "Int"; value: string } // value as string 28 | | { type: "Uint"; value: string } // value as string 29 | | { type: "Bool"; value: boolean } 30 | | { type: "String"; value: string } 31 | | { type: "FixedArray"; value: SerializableToken[] } 32 | | { type: "Array"; value: SerializableToken[] } 33 | | { type: "Tuple"; value: SerializableToken[] }; 34 | 35 | export interface AccessListItem { 36 | address: string; // hex string of the address 37 | storageKeys: string[]; // array of hex strings representing storage keys 38 | } 39 | 40 | export type AccessList = AccessListItem[]; 41 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/KeyData.ts: -------------------------------------------------------------------------------- 1 | import { KeyPairString } from "near-api-js/lib/utils"; 2 | 3 | /** 4 | * Key data structure containing information about a trial key. 5 | */ 6 | export interface KeyData { 7 | publicKey: string; 8 | secretKey: string; 9 | trialId: number; 10 | mpcKey: string; 11 | } 12 | 13 | /** 14 | * Represents a trial key along with its associated account ID and MPC key. 15 | */ 16 | export interface TrialKey { 17 | derivationPath: string; 18 | trialAccountSecretKey: KeyPairString; 19 | trialAccountPublicKey: string; 20 | mpcKey: string; 21 | } 22 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/KeyUsage.ts: -------------------------------------------------------------------------------- 1 | import { AccountIdByChainId, UsageStats } from "./TrialAccountInfo"; 2 | 3 | /** 4 | * Associates a public key with its usage stats and trial ID. 5 | */ 6 | export interface KeyUsage { 7 | trialId: number; 8 | mpcKey: string; // PublicKey represented as a string 9 | accountId: AccountIdByChainId; 10 | usageStats: UsageStats; 11 | } 12 | 13 | /** 14 | * Structure representing a key with both a public key and MPC key. 15 | */ 16 | export interface KeyWithMPC { 17 | publicKey: string; // PublicKey represented as a string 18 | mpcKey: string; // MPC PublicKey represented as a string 19 | } 20 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/MPCSignature.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Result Type of MPC contract signature request. 3 | * Representing Affine Points on eliptic curve. 4 | * Example: { 5 | "big_r": { 6 | "affine_point": "031F2CE94AF69DF45EC96D146DB2F6D35B8743FA2E21D2450070C5C339A4CD418B" 7 | }, 8 | "s": { "scalar": "5AE93A7C4138972B3FE8AEA1638190905C6DB5437BDE7274BEBFA41DDAF7E4F6" 9 | }, 10 | "recovery_id": 0 11 | } 12 | */ 13 | 14 | export interface MPCSignature { 15 | big_r: { affine_point: string }; 16 | s: { scalar: string }; 17 | recovery_id: number; 18 | } 19 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/TrialAccountInfo.ts: -------------------------------------------------------------------------------- 1 | // lib/types/TrialAccountInfo.ts 2 | 3 | import { TrialData } from "./TrialData"; 4 | 5 | /** 6 | * Usage statistics for the trial account. 7 | */ 8 | export interface UsageStats { 9 | interactionsPerDay: { [timestamp: number]: number }; // Day timestamp to interaction count 10 | totalInteractions: number; 11 | methodsCalled: { [methodName: string]: number }; // method_name to count 12 | contractsCalled: { [contractId: string]: number }; // contract_id to count 13 | gasUsed: string; // Represented as a string to handle large numbers 14 | depositUsed: string; // Represented as a string to handle large amounts 15 | } 16 | 17 | /** 18 | * Represents usage stats and account information for a trial account. 19 | */ 20 | export interface TrialAccountInfo { 21 | trialId: number; 22 | trialData: TrialData; 23 | mpcKey: string; // Corresponds to the public key in the Rust implementation 24 | accountIdByChainId: AccountIdByChainId; 25 | usageStats: UsageStats; 26 | } 27 | 28 | export type AccountIdByChainId = Record; 29 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/TrialData.ts: -------------------------------------------------------------------------------- 1 | // lib/types/TrialData.ts 2 | 3 | import { 4 | UsageConstraints, 5 | InteractionLimits, 6 | ExitConditions, 7 | } from "./Constraints"; 8 | 9 | import { ExtEVMConstraints, NEARConstraints } from "./ChainConstraints"; 10 | 11 | /** 12 | * Data required to create a trial. 13 | */ 14 | export interface TrialData { 15 | constraintsByChainId: { 16 | NEAR?: NEARConstraints; 17 | EVM?: ExtEVMConstraints; 18 | }; 19 | usageConstraints: UsageConstraints | null; 20 | interactionLimits: InteractionLimits | null; 21 | exitConditions: ExitConditions | null; 22 | expirationTime: number | null; 23 | creatorAccountId?: string; 24 | } 25 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/index.ts: -------------------------------------------------------------------------------- 1 | // lib/types/index.ts 2 | 3 | export * from "./BigInts"; 4 | export * from "./EVMTypes"; 5 | export * from "./TrialAccountInfo"; 6 | export * from "./Constraints"; 7 | export * from "./ActionToPerform"; 8 | export * from "./TrialData"; 9 | export * from "./KeyData"; 10 | export * from "./MPCSignature"; 11 | export * from "./Chain"; 12 | export * from "./KeyUsage"; 13 | export * from "./util"; 14 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/types/util.ts: -------------------------------------------------------------------------------- 1 | // lib/types/util.ts 2 | 3 | // Utility to convert a string from snake_case to camelCase 4 | export function snakeToCamel(str: string): string { 5 | return str.replace(/(_\w)/g, (m) => m[1].toUpperCase()); 6 | } 7 | 8 | // Recursive function to convert all keys of an object from snake_case to camelCase 9 | export function convertKeysToCamelCase(obj: any): any { 10 | if (Array.isArray(obj)) { 11 | return obj.map((item) => convertKeysToCamelCase(item)); 12 | } else if (obj !== null && obj.constructor === Object) { 13 | return Object.keys(obj).reduce((result: any, key: string) => { 14 | const camelCaseKey = snakeToCamel(key); 15 | result[camelCaseKey] = convertKeysToCamelCase(obj[key]); 16 | return result; 17 | }, {}); 18 | } 19 | return obj; // Return if neither object nor array 20 | } 21 | 22 | /** 23 | * Converts an object's keys from camelCase to snake_case recursively, 24 | * but keeps all-uppercase keys unchanged. 25 | * 26 | * @param obj - The object to be converted. 27 | * @returns The new object with snake_case keys. 28 | */ 29 | export function toSnakeCase(obj: any): any { 30 | if (Array.isArray(obj)) { 31 | return obj.map((item) => toSnakeCase(item)); 32 | } else if (obj && typeof obj === "object" && obj.constructor === Object) { 33 | return Object.keys(obj).reduce((acc: any, key: string) => { 34 | // Check if the key is all uppercase 35 | const snakeKey = /^[A-Z0-9_]+$/.test(key) 36 | ? key 37 | : key.replace(/([A-Z])/g, "_$1").toLowerCase(); 38 | acc[snakeKey] = toSnakeCase(obj[key]); 39 | return acc; 40 | }, {}); 41 | } 42 | return obj; 43 | } 44 | -------------------------------------------------------------------------------- /packages/trial-accounts/src/lib/wallet-selector/types.ts: -------------------------------------------------------------------------------- 1 | import { InstantLinkWallet, NetworkId } from "@near-wallet-selector/core"; 2 | import { KeypomTrialSelector } from "./wallet"; 3 | 4 | export const FAILED_EXECUTION_OUTCOME: any = { 5 | final_execution_status: "NONE", 6 | status: { 7 | Failure: { 8 | error_message: "Invalid Trial Action", 9 | error_type: "keypom-trial-error", 10 | }, 11 | }, 12 | transaction: {}, 13 | transaction_outcome: { 14 | id: "", 15 | outcome: { 16 | logs: [], 17 | receipt_ids: [], 18 | tokens_burnt: "0", 19 | executor_id: "", 20 | gas_burnt: 0, 21 | status: { 22 | Failure: { 23 | error_message: "Invalid Trial Action", 24 | error_type: "keypom-trial-error", 25 | }, 26 | }, 27 | }, 28 | }, 29 | receipts_outcome: [ 30 | { 31 | id: "", 32 | outcome: { 33 | logs: [], 34 | receipt_ids: [], 35 | gas_burnt: 0, 36 | tokens_burnt: "0", 37 | executor_id: "", 38 | status: { 39 | Failure: { 40 | error_message: "Invalid Trial Action", 41 | error_type: "keypom-trial-error", 42 | }, 43 | }, 44 | }, 45 | }, 46 | ], 47 | }; 48 | 49 | export interface SignInOptions { 50 | contractId?: string; 51 | allowance?: string; 52 | methodNames?: string[]; 53 | } 54 | 55 | export interface KeypomInitializeOptions { 56 | keypomWallet: KeypomTrialSelector; 57 | } 58 | 59 | export interface OneClickParams { 60 | networkId: NetworkId; 61 | contractId: string; 62 | allowance?: string; 63 | methodNames?: string[]; 64 | } 65 | 66 | export const isOneClickParams = (params: OneClickParams): boolean => 67 | typeof params.networkId === "string" && 68 | (params.networkId === "testnet" || params.networkId === "mainnet"); 69 | 70 | export type KeypomWalletInstant = InstantLinkWallet & { 71 | networkId: string; 72 | getContractId(): string; 73 | switchAccount(id: string): Promise; 74 | getAccountId(): string; 75 | isSignedIn: () => Promise; 76 | getAvailableBalance: () => Promise; 77 | showModal(); 78 | }; 79 | 80 | export type AddKeyPermission = 81 | | "FullAccess" 82 | | { 83 | receiverId: string; 84 | allowance?: string; 85 | methodNames?: Array; 86 | }; 87 | -------------------------------------------------------------------------------- /packages/trial-accounts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.node.json", 3 | "compilerOptions": { 4 | "preserveSymlinks": false, 5 | "outDir": "./lib", 6 | "baseUrl": ".", 7 | "lib": [ 8 | "ES2020", 9 | "DOM" 10 | ], // Add "DOM" here for browser types 11 | "paths": { 12 | "@near-js/types/*": [ 13 | "node_modules/@near-js/types/lib/*" 14 | ], 15 | "@near-js/types/src/provider/protocol": [ 16 | "node_modules/@near-js/types/lib/provider/protocol" 17 | ] 18 | } 19 | }, 20 | "files": [ 21 | "src/index.ts" 22 | ], 23 | "types": [ 24 | "node" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /packages/trial-accounts/typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://typedoc.org/schema.json", 3 | "entryPoints": ["./src/index.ts"], 4 | "out": "docs" 5 | } -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/*" -------------------------------------------------------------------------------- /static/claim-linkdrop-asset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keypom/keypom-js/a422762d00f843fefd4e5f46bba180ae69c376ea/static/claim-linkdrop-asset.png -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": true, 4 | "module": "commonjs", 5 | "target": "es2020", 6 | "moduleResolution": "node", 7 | "alwaysStrict": true, 8 | "declaration": true, 9 | "preserveSymlinks": true, 10 | "preserveWatchOutput": true, 11 | "pretty": false, 12 | "forceConsistentCasingInFileNames": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "noImplicitAny": false, 15 | "noImplicitReturns": true, 16 | "noUnusedLocals": true, 17 | "experimentalDecorators": true, 18 | "resolveJsonModule": true 19 | // "types": ["node"] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.browser.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "lib": [ 5 | "es2020", 6 | "esnext", 7 | "dom" 8 | ] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "lib": [ 5 | "es2020", 6 | "esnext" 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "inputs": ["src/**/*.ts", "test/**/*.js"], 7 | "outputs": ["dist/**", "lib/**"] 8 | }, 9 | "lint": { 10 | "inputs": ["src/**/*.ts", "test/**/*.js"], 11 | "outputs": [] 12 | }, 13 | "lint:js": { 14 | "inputs": ["test/**/*.js"], 15 | "outputs": [] 16 | }, 17 | "lint:js:fix": { 18 | "inputs": ["test/**/*.js"], 19 | "outputs": [] 20 | }, 21 | "lint:ts": { 22 | "inputs": ["src/**/*.ts"], 23 | "outputs": [] 24 | }, 25 | "lint:ts:fix": { 26 | "inputs": ["src/**/*.ts"], 27 | "outputs": [] 28 | }, 29 | "clean": { 30 | "outputs": [], 31 | "cache": false 32 | } 33 | } 34 | } 35 | --------------------------------------------------------------------------------