diff --git a/.github/workflows/build-action.yml b/.github/workflows/build-action.yml index 330e34159d..816d2c6a4c 100644 --- a/.github/workflows/build-action.yml +++ b/.github/workflows/build-action.yml @@ -94,3 +94,29 @@ jobs: token: ${{ secrets.NPM_TOKEN }} env: INPUT_TOKEN: ${{ secrets.NPM_TOKEN }} + + Release-mina-signer-on-NPM: + timeout-minutes: 180 + runs-on: ubuntu-latest + needs: [Build-And-Test-Server, Build-And-Test-Web] + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + - name: Setup Node + uses: actions/setup-node@v2 + with: + node-version: '18' + - name: Build mina-signer + run: | + npm ci + cd src/mina-signer + npm ci + npm run prepublishOnly + - name: Publish to NPM if version has changed + uses: JS-DevTools/npm-publish@v1 + if: github.ref == 'refs/heads/main' + with: + token: ${{ secrets.NPM_TOKEN }} + package: './src/mina-signer/package.json' + env: + INPUT_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/src/mina-signer/README.md b/src/mina-signer/README.md new file mode 100644 index 0000000000..55c7ba3885 --- /dev/null +++ b/src/mina-signer/README.md @@ -0,0 +1,56 @@ +# Mina Signer + +This is a NodeJS SDK that allows you to sign strings, payments, and delegations using Mina's key pairs for various specified networks. + +# Install + +```bash +yarn add mina-signer +# or with npm: +npm install --save mina-signer +``` + +# Usage + +```js +import Client from 'mina-signer'; +const client = new Client({ network: 'mainnet' }); + +// Generate keys +let keypair = client.genKeys(); + +// Sign and verify message +let signed = client.signMessage('hello', keypair); +if (client.verifyMessage(signed)) { + console.log('Message was verified successfully'); +} + +// Sign and verify a payment +let signedPayment = client.signPayment( + { + to: keypair.publicKey, + from: keypair.publicKey, + amount: 1, + fee: 1, + nonce: 0, + }, + keypair.privateKey +); +if (client.verifyPayment(signedPayment)) { + console.log('Payment was verified successfully'); +} + +// Sign and verify a stake delegation +const signedDelegation = client.signStakeDelegation( + { + to: keypair.publicKey, + from: keypair.publicKey, + fee: '1', + nonce: '0', + }, + keypair.privateKey +); +if (client.verifyStakeDelegation(signedDelegation)) { + console.log('Delegation was verified successfully'); +} +``` diff --git a/src/mina-signer/build-cjs.sh b/src/mina-signer/build-cjs.sh new file mode 100755 index 0000000000..9c939d28cc --- /dev/null +++ b/src/mina-signer/build-cjs.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +cp index.cjs dist/node/mina-signer/index.cjs +cp index.d.ts dist/node/mina-signer/index.d.ts + +npx esbuild --bundle --minify dist/node/mina-signer/index.cjs --outfile=./dist/node/mina-signer/index.cjs --format=cjs --target=es2021 --platform=node --allow-overwrite=true diff --git a/src/mina-signer/build-web.sh b/src/mina-signer/build-web.sh new file mode 100755 index 0000000000..d3a0305851 --- /dev/null +++ b/src/mina-signer/build-web.sh @@ -0,0 +1,7 @@ +#!/bin/bash +set -e + +tsc -p ../../tsconfig.mina-signer-web.json +node moveWebFiles.js +npx esbuild --bundle --minify dist/tmp/mina-signer/MinaSigner.js --outfile=./dist/web/index.js --format=esm --target=es2021 +npx rimraf dist/tmp diff --git a/src/mina-signer/index.cjs b/src/mina-signer/index.cjs new file mode 100644 index 0000000000..ac595416dd --- /dev/null +++ b/src/mina-signer/index.cjs @@ -0,0 +1,5 @@ +// this file is a wrapper for supporting commonjs imports + +let Client = require('./MinaSigner.js'); + +module.exports = Client.default; diff --git a/src/mina-signer/index.d.ts b/src/mina-signer/index.d.ts new file mode 100644 index 0000000000..d021add39e --- /dev/null +++ b/src/mina-signer/index.d.ts @@ -0,0 +1,5 @@ +// this file is a wrapper for supporting types in both commonjs and esm projects + +import Client from './MinaSigner.js'; + +export = Client; diff --git a/src/mina-signer/moveWebFiles.js b/src/mina-signer/moveWebFiles.js new file mode 100644 index 0000000000..a02f08ddbc --- /dev/null +++ b/src/mina-signer/moveWebFiles.js @@ -0,0 +1,10 @@ +import glob from 'glob'; +import { move } from 'fs-extra'; + +let webFiles = glob.sync('./dist/tmp/**/*.web.js'); + +await Promise.all( + webFiles.map((file) => + move(file, file.replace('.web.js', '.js'), { overwrite: true }) + ) +); diff --git a/src/mina-signer/package-lock.json b/src/mina-signer/package-lock.json new file mode 100644 index 0000000000..2d93b7d7af --- /dev/null +++ b/src/mina-signer/package-lock.json @@ -0,0 +1,27 @@ +{ + "name": "mina-signer", + "version": "1.7.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "mina-signer", + "version": "1.7.0", + "license": "Apache-2.0", + "dependencies": { + "blakejs": "^1.2.1", + "js-sha256": "^0.9.0" + } + }, + "node_modules/blakejs": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" + }, + "node_modules/js-sha256": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz", + "integrity": "sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==" + } + } +} diff --git a/src/mina-signer/package.json b/src/mina-signer/package.json index b3187b69b2..f355756e0e 100644 --- a/src/mina-signer/package.json +++ b/src/mina-signer/package.json @@ -1,11 +1,14 @@ { "name": "mina-signer", "description": "Node API for signing transactions on various networks for Mina Protocol", - "version": "1.3.0", + "version": "1.7.0", "type": "module", "scripts": { "build": "tsc -p ../../tsconfig.mina-signer.json", - "test": "for f in ./**/*.test.ts; do NODE_OPTIONS=--experimental-vm-modules npx jest $f || exit 1; done" + "build:cjs": "./build-cjs.sh", + "build:web": "./build-web.sh", + "test": "for f in ./**/*.test.ts; do NODE_OPTIONS=--experimental-vm-modules npx jest $f || exit 1; done", + "prepublishOnly": "npx rimraf ./dist && npm run build && npm run build:cjs && npm run build:web" }, "keywords": [ "mina", @@ -17,9 +20,20 @@ "homepage": "https://minaprotocol.com/", "repository": "https://github.com/MinaProtocol/mina", "bugs": "https://github.com/MinaProtocol/mina/issues", - "main": "dist/src/MinaSigner.js", - "types": "dist/src/MinaSigner.d.ts", + "main": "dist/node/mina-signer/MinaSigner.js", + "types": "dist/node/mina-signer/index.d.ts", + "exports": { + "web": "./dist/web/index.js", + "require": "./dist/node/mina-signer/index.cjs", + "node": "./dist/node/mina-signer/MinaSigner.js", + "default": "./dist/web/index.js" + }, "files": [ - "dist" - ] + "dist", + "README.md" + ], + "dependencies": { + "blakejs": "^1.2.1", + "js-sha256": "^0.9.0" + } } diff --git a/src/mina-signer/src/rosetta.ts b/src/mina-signer/src/rosetta.ts index 0cae04d1a8..2b0c99e0e0 100644 --- a/src/mina-signer/src/rosetta.ts +++ b/src/mina-signer/src/rosetta.ts @@ -48,7 +48,7 @@ function fieldFromHex( return [binable.fromBytes(bytes), paddingBit]; } -// TODO: clean up this logic, was copied over from Ocaml code +// TODO: clean up this logic, was copied over from OCaml code function rosettaTransactionToSignedCommand({ signature, payment, diff --git a/src/mina-signer/tests/client.test.ts b/src/mina-signer/tests/client.test.ts index 2ed2eb191d..ca0cce3934 100644 --- a/src/mina-signer/tests/client.test.ts +++ b/src/mina-signer/tests/client.test.ts @@ -1,4 +1,4 @@ -import Client from '../dist/mina-signer/MinaSigner.js'; +import Client from '../dist/node/mina-signer/MinaSigner.js'; describe('Client Class Initialization', () => { let client; diff --git a/src/mina-signer/tests/keypair.test.ts b/src/mina-signer/tests/keypair.test.ts index 1f00593094..5e3e48dd59 100644 --- a/src/mina-signer/tests/keypair.test.ts +++ b/src/mina-signer/tests/keypair.test.ts @@ -1,4 +1,4 @@ -import Client from '../dist/mina-signer/MinaSigner.js'; +import Client from '../dist/node/mina-signer/MinaSigner.js'; describe('Keypair', () => { let client: Client; diff --git a/src/mina-signer/tests/message.test.ts b/src/mina-signer/tests/message.test.ts index ef7cd279b1..7f5ffcd27d 100644 --- a/src/mina-signer/tests/message.test.ts +++ b/src/mina-signer/tests/message.test.ts @@ -1,9 +1,9 @@ -import Client from '../dist/mina-signer/MinaSigner.js'; +import Client from '../dist/node/mina-signer/MinaSigner.js'; import type { Keypair, Signed, Message, -} from '../dist/mina-signer/src/TSTypes.js'; +} from '../dist/node/mina-signer/src/TSTypes.js'; describe('Message', () => { describe('Mainnet network', () => { diff --git a/src/mina-signer/tests/party.test.ts b/src/mina-signer/tests/party.test.ts index 0998ee88c2..0172ce561f 100644 --- a/src/mina-signer/tests/party.test.ts +++ b/src/mina-signer/tests/party.test.ts @@ -1,6 +1,6 @@ -import { ZkappCommand } from '../dist/provable/gen/transaction-bigint.js'; -import * as TransactionJson from '../dist/provable/gen/transaction-json.js'; -import Client from '../dist/mina-signer/MinaSigner.js'; +import { ZkappCommand } from '../dist/node/provable/gen/transaction-bigint.js'; +import * as TransactionJson from '../dist/node/provable/gen/transaction-json.js'; +import Client from '../dist/node/mina-signer/MinaSigner.js'; let dummyFeePayer = ZkappCommand.toJSON(ZkappCommand.emptyValue()).feePayer; diff --git a/src/mina-signer/tests/payment.test.ts b/src/mina-signer/tests/payment.test.ts index 84932e4026..007686d701 100644 --- a/src/mina-signer/tests/payment.test.ts +++ b/src/mina-signer/tests/payment.test.ts @@ -1,9 +1,9 @@ -import Client from '../dist/mina-signer/MinaSigner.js'; +import Client from '../dist/node/mina-signer/MinaSigner.js'; import type { Keypair, Signed, Payment, -} from '../dist/mina-signer/src/TSTypes.js'; +} from '../dist/node/mina-signer/src/TSTypes.js'; describe('Payment', () => { describe('Mainnet network', () => { diff --git a/src/mina-signer/tests/rosetta.test.ts b/src/mina-signer/tests/rosetta.test.ts index 5613c53b2c..73f6ecae90 100644 --- a/src/mina-signer/tests/rosetta.test.ts +++ b/src/mina-signer/tests/rosetta.test.ts @@ -1,4 +1,4 @@ -import Client from '../dist/mina-signer/MinaSigner.js'; +import Client from '../dist/node/mina-signer/MinaSigner.js'; describe('Rosetta', () => { let client: Client; diff --git a/src/mina-signer/tests/stake-delegation.test.ts b/src/mina-signer/tests/stake-delegation.test.ts index 8a0049f14e..4749b0cda4 100644 --- a/src/mina-signer/tests/stake-delegation.test.ts +++ b/src/mina-signer/tests/stake-delegation.test.ts @@ -1,9 +1,9 @@ -import Client from '../dist/mina-signer/MinaSigner.js'; +import Client from '../dist/node/mina-signer/MinaSigner.js'; import type { Keypair, Signed, StakeDelegation, -} from '../dist/mina-signer/src/TSTypes.js'; +} from '../dist/node/mina-signer/src/TSTypes.js'; describe('Stake Delegation', () => { describe('Mainnet network', () => { diff --git a/tsconfig.json b/tsconfig.json index b2ca633b76..268b0f8b3a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,6 @@ "declaration": true, // declaration files are how library consumers get our types "noEmitOnError": false, // avoid accidentally shipping with type errors "allowJs": true, // to use JSDoc in some places where TS would be too cumbersome - "sourceMap": true, + "sourceMap": true } } diff --git a/tsconfig.mina-signer-web.json b/tsconfig.mina-signer-web.json new file mode 100644 index 0000000000..f6172c4115 --- /dev/null +++ b/tsconfig.mina-signer-web.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.mina-signer.json", + "include": ["./src/mina-signer/MinaSigner.ts", "./src/**/*.web.ts"], + "compilerOptions": { + "outDir": "src/mina-signer/dist/tmp" + } +} diff --git a/tsconfig.mina-signer.json b/tsconfig.mina-signer.json index ed67f08e43..9a6debaf3a 100644 --- a/tsconfig.mina-signer.json +++ b/tsconfig.mina-signer.json @@ -3,7 +3,7 @@ "exclude": ["./src/**/*.unit-test.ts"], "compilerOptions": { "rootDir": "./src", - "outDir": "src/mina-signer/dist", + "outDir": "src/mina-signer/dist/node", "baseUrl": ".", // affects where output files end up "target": "es2020", // goal: ship *the most modern syntax* that is supported by *all* browsers that support our Wasm "module": "es2022", // allow top-level await