diff --git a/README.md b/README.md index c2410c7..55eebc5 100644 --- a/README.md +++ b/README.md @@ -50,9 +50,11 @@ molecules/ └── icp/ ├── └── icp-auth └── ton/ -├── └── ton-auth +├── └── ton-auth/ +└── massa/ + └── massa-auth └── near/ - └── n-view-state +└── └── n-view-state └── ark/ ├── ├── resolve ├── └── state @@ -73,6 +75,7 @@ molecules/ | TRON (`trx`) | `trx.molecule.sh` | `trx-auth` | 🟩 | | Internet Protocol (`ICP`) | `icp.molecule.sh` | `icp-auth` | 🟩 | | TON (`ton`) | `ton.molecule.sh` | `ton-auth` | 🟩 | +| Massa (`massa`) | `massa.molecule.sh` | `massa-auth` | 🟩 | | NEAR (`near`) | `near.molecule.sh` | `n-view-state` | 🟩 | | Ark Protocol (`ark`) | `ark.molecule.sh` | `state` `resolve` `soark/domain` | 🟩/🟨 | Randomization (`rand`) | `rand.molecule.sh` | `generate` | 🟩/🟨 | @@ -109,6 +112,8 @@ The following EXM contracts integrate [molecule.sh](http://molecule.sh) atoms to - TON authentication: Simple name registry contract. [example](./examples/ton-signing/wtf.md) +- Massa authentication: Simple name registry contract. [example](./examples/massa-signing/wtf.md) + - Getting [Ark Protocol](https://ark.decent.land) identity object. [example](./examples/ark-resolving/wtf.md) - GPT3 integration in a smart contract. [example](./examples/gpt3/wtf.md) diff --git a/examples/massa-signing/contract.js b/examples/massa-signing/contract.js new file mode 100644 index 0000000..6e8fe95 --- /dev/null +++ b/examples/massa-signing/contract.js @@ -0,0 +1,42 @@ +export async function handle(state, action) { + const input = action.input; + + const names = state.names; + const signatures = state.signatures; + const verification_message = state.verification_message; + const massa_molecule_endpoint = state.massa_molecule_endpoint; + + if (input.function === "register") { + const name = input.name; + const caller = input.caller; + const signature = input.signature; + + ContractAssert(name.trim().length, "error invalid name"); + ContractAssert(!(name in names), "name already registered"); + ContractAssert(caller && signature, "missing required arguments"); + ContractAssert( + !signatures.includes(signature), + "error signed message used" + ); + + const message = btoa(verification_message); + const res = await _moleculeSignatureVerification(caller, message, signature); + state.names[res.address] = `${name.trim()}.massa`; + signatures.push(signature); + + return { state }; + } + + async function _moleculeSignatureVerification(caller, message, signature) { + try { + const isValid = await EXM.deterministicFetch( + `${massa_molecule_endpoint}/massa-auth/${caller}/${message}/${signature}` + ); + ContractAssert(isValid.asJSON()?.result, "unauthorized caller"); + return isValid.asJSON(); + } catch (error) { + throw new ContractError("molecule res error"); + } + } +} + diff --git a/examples/massa-signing/contract.json b/examples/massa-signing/contract.json new file mode 100644 index 0000000..45e297f --- /dev/null +++ b/examples/massa-signing/contract.json @@ -0,0 +1,7 @@ +{ + "names": {}, + "signatures": [], + "verification_message": "hello world", + "massa_molecule_endpoint": "http://massa.molecule.sh" +} + diff --git a/examples/massa-signing/wtf.md b/examples/massa-signing/wtf.md new file mode 100644 index 0000000..4ec7fc9 --- /dev/null +++ b/examples/massa-signing/wtf.md @@ -0,0 +1,25 @@ +## About +The EXM contract below is an example implementation of a contract that uses [Massa.net](https://massa.net) for contract's caller authentication (`action.caller`), empowered by `massa-auth` atom of `massa` molecule. + +#### Contract +- Live deployment: [EDzDQDgaStQEGmuDH9X1DxQGY5o7F11Jyj4AYSFL9MI](https://api.exm.dev/read/EDzDQDgaStQEGmuDH9X1DxQGY5o7F11Jyj4AYSFL9MI) +- source code: [./contract.js](./contract.js) + +## Prerequisites + +- EXM SDK +```console +npm i -g @execution-machine/sdk +``` + +- EXM API token ID: visit [exm.dev](https://exm.dev) + +## Iteracting with the contract +To register a `name` in the contract example, you have first to sign with your wallet the message used for verification in the contract's example which is `hello world` + +`signature` and caller (`publicKey`) should be both passed under base58 encoding format. + +#### EXM CLI +```console +exm function:write EDzDQDgaStQEGmuDH9X1DxQGY5o7F11Jyj4AYSFL9MI --input '{"function": "register", "name": "buildooor", "signature": "$MASSA_SIGNATURE", "caller": "$MASSA_PUBLIC_KEY"}' --token EXM_TOKEN_ID +``` diff --git a/examples/ton-signing/wtf.md b/examples/ton-signing/wtf.md index 516950f..95dfe76 100644 --- a/examples/ton-signing/wtf.md +++ b/examples/ton-signing/wtf.md @@ -1,5 +1,5 @@ ## About -The EXM contract below is an example implementation of a contract that uses TON network [ICP](https://ton.org) for contract's caller authentication (`action.caller`), empowered by `ton-auth` atom of `ton` molecule. +The EXM contract below is an example implementation of a contract that uses TON network for contract's caller authentication (`action.caller`), empowered by `ton-auth` atom of `ton` molecule. #### Contract - Live deployment: [lpLm1AKAhY-AZPMFwXVOLkMe7UDtaoNiG3keNMJEapg](https://api.exm.dev/read/lpLm1AKAhY-AZPMFwXVOLkMe7UDtaoNiG3keNMJEapg) diff --git a/package.json b/package.json index ca3ea60..eace64a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "molecule", - "version": "0.1.5", + "version": "0.1.6", "type": "module", "description": "reusable EXM components and helper functions for a faster development", "main": "./src/api.js", diff --git a/src/api.js b/src/api.js index 824c2a4..3df8464 100644 --- a/src/api.js +++ b/src/api.js @@ -18,6 +18,7 @@ import { isSubstrateSigner } from "./molecules/substrate/atoms/verifySigner.js"; import { isTrxSigner } from "./molecules/trx/atoms/verifySigner.js"; import { isIcpSigner } from "./molecules/icp/atoms/verifySigner.js"; import { isTonSigner } from "./molecules/ton/atoms/verifySigner.js"; +import { isMassaSigner } from "./molecules/massa/atoms/verifySigner.js"; import { readNearOracleState } from "./molecules/near/atoms/read-contract.js"; import base64url from "base64url"; @@ -180,6 +181,22 @@ app.get("/ton-auth/:pubkey/:message/:signature", async (req, res) => { } }); +app.get("/massa-auth/:pubkey/:message/:signature", async (req, res) => { + try { + res.setHeader("Content-Type", "application/json"); + + assert.equal(checkSubdomain(req, "massa"), true); + const { pubkey, message, signature } = req.params; + const response = await isMassaSigner(message, pubkey, signature); + res.send(response); + return; + } catch (error) { + console.log(error) + res.send({ result: false, address: null }); + return; + } +}); + app.get("/n-view-state/:network/:address", async (req, res) => { try { res.setHeader("Content-Type", "application/json"); diff --git a/src/molecules/massa/atoms/verifySigner.js b/src/molecules/massa/atoms/verifySigner.js new file mode 100644 index 0000000..ad123cb --- /dev/null +++ b/src/molecules/massa/atoms/verifySigner.js @@ -0,0 +1,14 @@ +import { MOLECULE_API_ENDPOINT } from "../../../utils/constants.js" +import axios from "axios"; + +export async function isMassaSigner(message, pubkey, signature) { + try { + const result = await axios.get( + `${MOLECULE_API_ENDPOINT}/massa/${pubkey}/${message}/${signature}` + ); + + return result?.data;; + } catch (error) { + return { result: false, address: null }; + } +} diff --git a/src/molecules/ton/atoms/verifySigner.js b/src/molecules/ton/atoms/verifySigner.js index 258009c..c7c1bfd 100644 --- a/src/molecules/ton/atoms/verifySigner.js +++ b/src/molecules/ton/atoms/verifySigner.js @@ -1,10 +1,10 @@ -import { TONWEB_ENDPOINT } from "../utils/constants.js"; +import { MOLECULE_API_ENDPOINT } from "../../../utils/constants.js"; import axios from "axios"; export async function isTonSigner(message, pubkey, signature) { try { const result = await axios.get( - `${TONWEB_ENDPOINT}/${pubkey}/${message}/${signature}` + `${MOLECULE_API_ENDPOINT}/tonweb/${pubkey}/${message}/${signature}` ); return result?.data;; diff --git a/src/molecules/ton/utils/constants.js b/src/molecules/ton/utils/constants.js deleted file mode 100644 index 930c74c..0000000 --- a/src/molecules/ton/utils/constants.js +++ /dev/null @@ -1 +0,0 @@ -export const TONWEB_ENDPOINT = `https://tonweb-wrapper.herokuapp.com/tonweb`; \ No newline at end of file diff --git a/src/utils/constants.js b/src/utils/constants.js index 1cf538b..465f3d6 100644 --- a/src/utils/constants.js +++ b/src/utils/constants.js @@ -10,6 +10,9 @@ export const MOLECULES = [ "icp", "ton", "near", + "massa", "substrate", "rand", ]; + +export const MOLECULE_API_ENDPOINT = `https://molecule-apis-wrapper.herokuapp.com`;