-
Notifications
You must be signed in to change notification settings - Fork 32
feat: add superise wallet #330
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
87b1d04
c77501d
e5b73f1
d03cb33
b5699bd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| import { encodeSvgToImgSrc } from "./utils.js"; | ||
|
|
||
| export const SUPERISE_SVG = encodeSvgToImgSrc(` | ||
| <svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg"> | ||
| <g clip-path="url(#clip0_2713_6523)"> | ||
| <rect width="1024" height="1024" rx="240" fill="#F9FF8C"/> | ||
| <g filter="url(#filter0_f_2713_6523)"> | ||
| <ellipse cx="758.248" cy="462.408" rx="700.524" ry="503.674" transform="rotate(56.0085 758.248 462.408)" fill="url(#paint0_linear_2713_6523)"/> | ||
| </g> | ||
| <g filter="url(#filter1_f_2713_6523)"> | ||
| <ellipse cx="121.048" cy="422.492" rx="536.031" ry="484.703" transform="rotate(-174.893 121.048 422.492)" fill="url(#paint1_linear_2713_6523)"/> | ||
| </g> | ||
| <g filter="url(#filter2_f_2713_6523)"> | ||
| <ellipse cx="632.696" cy="552.825" rx="632.696" ry="552.825" transform="matrix(0.969162 -0.246425 -0.246425 -0.969162 -97.5404 1805.38)" fill="url(#paint2_linear_2713_6523)"/> | ||
| </g> | ||
| <g filter="url(#filter3_f_2713_6523)"> | ||
| <ellipse cx="421.147" cy="83.6366" rx="303.349" ry="383.001" transform="rotate(56.0085 421.147 83.6366)" fill="url(#paint3_linear_2713_6523)"/> | ||
| </g> | ||
| <g filter="url(#filter4_d_2713_6523)"> | ||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M244.988 292.094C240.051 292.094 236.049 296.137 236.049 301.121V373.487C236.049 378.476 240.051 382.515 244.988 382.515H641.452C670.495 382.515 693.823 407.702 691.174 437.594C688.81 464.234 664.353 483.392 637.877 483.392H244.988C240.051 483.392 236.049 487.435 236.049 492.419V564.79C236.049 569.774 240.051 573.822 244.988 573.822H635.936C707.153 573.822 770.989 522.283 779.767 450.871C790.291 365.247 724.158 292.094 641.452 292.094H244.988Z" fill="url(#paint4_linear_2713_6523)"/> | ||
| <mask id="mask0_2713_6523" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="236" y="292" width="545" height="282"> | ||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M244.988 292.094C240.051 292.094 236.049 296.137 236.049 301.121V373.487C236.049 378.476 240.051 382.515 244.988 382.515H641.452C670.495 382.515 693.823 407.702 691.174 437.594C688.81 464.234 664.353 483.392 637.877 483.392H244.988C240.051 483.392 236.049 487.435 236.049 492.419V564.79C236.049 569.774 240.051 573.822 244.988 573.822H635.936C707.153 573.822 770.989 522.283 779.767 450.871C790.291 365.247 724.158 292.094 641.452 292.094H244.988Z" fill="white"/> | ||
| </mask> | ||
| <g mask="url(#mask0_2713_6523)"/> | ||
| <path fill-rule="evenodd" clip-rule="evenodd" d="M787.951 722.854C787.951 727.967 783.6 732.174 778.492 732.093C651.689 729.968 575.418 685.321 507.959 645.806C443.886 608.302 344.174 575.752 244.923 573.901C239.982 573.809 236.049 569.881 236.049 564.94V492.737C236.049 487.614 240.284 483.389 245.407 483.475C368.766 485.6 487.746 529.206 553.637 567.78C616.765 604.738 676.497 639.71 778.89 641.657C783.836 641.753 787.951 645.696 787.951 650.646V722.854Z" fill="white"/> | ||
| </g> | ||
| </g> | ||
| <defs> | ||
| <filter id="filter0_f_2713_6523" x="-114.273" y="-483.219" width="1745.04" height="1891.25" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||
| <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/> | ||
| <feGaussianBlur stdDeviation="150" result="effect1_foregroundBlur_2713_6523"/> | ||
| </filter> | ||
| <filter id="filter1_f_2713_6523" x="-714.624" y="-362.675" width="1671.34" height="1570.33" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||
| <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/> | ||
| <feGaussianBlur stdDeviation="150" result="effect1_foregroundBlur_2713_6523"/> | ||
| </filter> | ||
| <filter id="filter2_f_2713_6523" x="-548.855" y="255.542" width="1856.54" height="1716.29" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||
| <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/> | ||
| <feGaussianBlur stdDeviation="150" result="effect1_foregroundBlur_2713_6523"/> | ||
| </filter> | ||
| <filter id="filter3_f_2713_6523" x="-238.927" y="-546.685" width="1320.15" height="1260.64" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||
| <feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/> | ||
| <feGaussianBlur stdDeviation="150" result="effect1_foregroundBlur_2713_6523"/> | ||
| </filter> | ||
| <filter id="filter4_d_2713_6523" x="218.449" y="278.014" width="587.102" height="475.2" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> | ||
| <feFlood flood-opacity="0" result="BackgroundImageFix"/> | ||
| <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> | ||
| <feOffset dy="3.52"/> | ||
| <feGaussianBlur stdDeviation="8.8"/> | ||
| <feComposite in2="hardAlpha" operator="out"/> | ||
| <feColorMatrix type="matrix" values="0 0 0 0 0.169928 0 0 0 0 0.266868 0 0 0 0 0.476054 0 0 0 0.25 0"/> | ||
| <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2713_6523"/> | ||
| <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2713_6523" result="shape"/> | ||
| </filter> | ||
| <linearGradient id="paint0_linear_2713_6523" x1="1188.46" y1="707.797" x2="371.373" y2="6.51421" gradientUnits="userSpaceOnUse"> | ||
| <stop stop-color="#FF3AED"/> | ||
| <stop offset="1" stop-color="#8E26FD"/> | ||
| </linearGradient> | ||
| <linearGradient id="paint1_linear_2713_6523" x1="-278.666" y1="723.942" x2="395.544" y2="11.6854" gradientUnits="userSpaceOnUse"> | ||
| <stop stop-color="#271AFF"/> | ||
| <stop offset="0.645888" stop-color="#34FFB4"/> | ||
| </linearGradient> | ||
| <linearGradient id="paint2_linear_2713_6523" x1="1163.54" y1="739.454" x2="381.131" y2="693.812" gradientUnits="userSpaceOnUse"> | ||
| <stop stop-color="#FF6B46"/> | ||
| <stop offset="1" stop-color="#FDFF7D"/> | ||
| </linearGradient> | ||
| <linearGradient id="paint3_linear_2713_6523" x1="249.658" y1="-78.2714" x2="470.006" y2="174.098" gradientUnits="userSpaceOnUse"> | ||
| <stop stop-color="#C13AFF"/> | ||
| <stop offset="1" stop-color="#2678FD"/> | ||
| </linearGradient> | ||
| <linearGradient id="paint4_linear_2713_6523" x1="235.68" y1="189.931" x2="191.244" y2="572.19" gradientUnits="userSpaceOnUse"> | ||
| <stop stop-color="white"/> | ||
| <stop offset="0.744734" stop-color="white"/> | ||
| <stop offset="1" stop-color="#9EABEB"/> | ||
| </linearGradient> | ||
| <clipPath id="clip0_2713_6523"> | ||
| <rect width="1024" height="1024" rx="240" fill="white"/> | ||
| </clipPath> | ||
| </defs> | ||
| </svg> | ||
| `); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import { secp256k1 } from "@noble/curves/secp256k1"; | ||
| import { BytesLike, bytesFrom } from "../../bytes/index.js"; | ||
| import { hashCkb } from "../../hasher/index.js"; | ||
| import { Hex, hexFrom } from "../../hex/index.js"; | ||
| import { numFrom } from "../../num/index.js"; | ||
|
|
||
| const SUPERISE_MESSAGE_PREFIX = "\x19SupeRISE Message:\n"; | ||
|
|
||
| /** | ||
| * @public | ||
| */ | ||
| function messageHashCkbSuperise(message: string | BytesLike): Hex { | ||
| const msg = typeof message === "string" ? message : hexFrom(message); | ||
| const buffer = bytesFrom( | ||
| `${SUPERISE_MESSAGE_PREFIX}${msg.length}${msg}`, | ||
| "utf8", | ||
| ); | ||
| return hashCkb(buffer); | ||
| } | ||
|
|
||
| /** | ||
| * @public | ||
| */ | ||
| export function verifyMessageSuperise( | ||
| message: string | BytesLike, | ||
| signature: string, | ||
| publicKey: string, | ||
| ): boolean { | ||
| const signatureBytes = bytesFrom(signature); | ||
| return secp256k1.verify( | ||
| new secp256k1.Signature( | ||
| numFrom(signatureBytes.slice(0, 32)), | ||
| numFrom(signatureBytes.slice(32, 64)), | ||
| ) | ||
| .addRecoveryBit(Number(numFrom(signatureBytes.slice(64, 65)))) | ||
| .toBytes(), | ||
| bytesFrom(messageHashCkbSuperise(message)), | ||
| bytesFrom(publicKey), | ||
| ); | ||
|
Comment on lines
+30
to
+39
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The implementation of This can be simplified by slicing the first 64 bytes of the signature and passing it directly to return secp256k1.verify(
signatureBytes.slice(0, 64),
bytesFrom(messageHashCkbSuperise(message)),
bytesFrom(publicKey),
); |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| node_modules/ | ||
| misc/ | ||
|
|
||
| *test.js | ||
| *test.ts | ||
| *test.d.ts | ||
| *test.d.ts.map | ||
| *spec.js | ||
| *spec.ts | ||
| *spec.d.ts | ||
| *spec.d.ts.map | ||
|
|
||
| tsconfig.json | ||
| tsconfig.*.json | ||
| eslint.config.mjs | ||
| .prettierrc | ||
| .prettierignore | ||
|
|
||
| tsconfig.tsbuildinfo | ||
| tsconfig.*.tsbuildinfo | ||
| .github/ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| node_modules/ | ||
|
|
||
| dist/ | ||
| dist.commonjs/ | ||
|
|
||
| .npmignore | ||
| .prettierrc | ||
| tsconfig.json | ||
| eslint.config.mjs | ||
| prettier.config.* | ||
|
|
||
| tsconfig.tsbuildinfo | ||
| .github/ | ||
|
|
||
| CHANGELOG.md |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| <p align="center"> | ||
| <a href="https://app.ckbccc.com/"> | ||
| <img alt="Logo" src="https://raw.githubusercontent.com/ckb-devrel/ccc/master/assets/logoAndText.svg" style="height: 8rem; max-width: 90%; padding: 0.5rem 0;" /> | ||
| </a> | ||
| </p> | ||
|
|
||
| <h1 align="center" style="font-size: 32px;"> | ||
| CCC's support for SupeRISE | ||
| </h1> | ||
|
|
||
| <p align="center"> | ||
| <a href="https://www.npmjs.com/package/@ckb-ccc/superise"><img | ||
| alt="NPM Version" src="https://img.shields.io/npm/v/%40ckb-ccc%2Fsuperise" | ||
| /></a> | ||
| <img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/ckb-devrel/ccc" /> | ||
| <img alt="GitHub last commit" src="https://img.shields.io/github/last-commit/ckb-devrel/ccc/master" /> | ||
| <img alt="GitHub branch check runs" src="https://img.shields.io/github/check-runs/ckb-devrel/ccc/master" /> | ||
| <a href="https://live.ckbccc.com/"><img | ||
| alt="Playground" src="https://img.shields.io/website?url=https%3A%2F%2Flive.ckbccc.com%2F&label=Playground" | ||
| /></a> | ||
| <a href="https://app.ckbccc.com/"><img | ||
| alt="App" src="https://img.shields.io/website?url=https%3A%2F%2Fapp.ckbccc.com%2F&label=App" | ||
| /></a> | ||
| <a href="https://docs.ckbccc.com/"><img | ||
| alt="Docs" src="https://img.shields.io/website?url=https%3A%2F%2Fdocs.ckbccc.com%2F&label=Docs" | ||
| /></a> | ||
| </p> | ||
|
|
||
| <p align="center"> | ||
| CCC - CKBers' Codebase is a one-stop solution for your CKB JS/TS ecosystem development. | ||
| <br /> | ||
| Empower yourself with CCC to discover the unlimited potential of CKB. | ||
| <br /> | ||
| Interoperate with wallets from different chain ecosystems. | ||
| <br /> | ||
| Fully enabling CKB's Turing completeness and cryptographic freedom power. | ||
| </p> | ||
|
|
||
| <h3 align="center"> | ||
| Read more about CCC on <a href="https://docs.ckbccc.com">our website</a> or <a href="https://github.com/ckb-devrel/ccc">GitHub Repo</a>. | ||
| </h3> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| // @ts-check | ||
|
|
||
| import eslint from "@eslint/js"; | ||
| import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; | ||
| import tseslint from "typescript-eslint"; | ||
|
|
||
| import { dirname } from "path"; | ||
| import { fileURLToPath } from "url"; | ||
|
|
||
| export default [ | ||
| ...tseslint.config({ | ||
| files: ["**/*.ts"], | ||
| extends: [ | ||
| eslint.configs.recommended, | ||
| ...tseslint.configs.recommendedTypeChecked, | ||
| ], | ||
| rules: { | ||
| "@typescript-eslint/no-unused-vars": [ | ||
| "error", | ||
| { | ||
| args: "all", | ||
| argsIgnorePattern: "^_", | ||
| caughtErrors: "all", | ||
| caughtErrorsIgnorePattern: "^_", | ||
| destructuredArrayIgnorePattern: "^_", | ||
| varsIgnorePattern: "^_", | ||
| ignoreRestSiblings: true, | ||
| }, | ||
| ], | ||
| "@typescript-eslint/unbound-method": ["error", { ignoreStatic: true }], | ||
| "@typescript-eslint/no-unsafe-member-access": "off", | ||
| "@typescript-eslint/require-await": "off", | ||
| "@typescript-eslint/only-throw-error": [ | ||
| "error", | ||
| { | ||
| allowThrowingAny: true, | ||
| allowThrowingUnknown: true, | ||
| allowRethrowing: true, | ||
| }, | ||
| ], | ||
| "@typescript-eslint/prefer-promise-reject-errors": [ | ||
| "error", | ||
| { | ||
| allowThrowingAny: true, | ||
| allowThrowingUnknown: true, | ||
| }, | ||
| ], | ||
| "no-empty": "off", | ||
| "prefer-const": [ | ||
| "error", | ||
| { ignoreReadBeforeAssign: true, destructuring: "all" }, | ||
| ], | ||
| }, | ||
| languageOptions: { | ||
| parserOptions: { | ||
| project: true, | ||
| tsconfigRootDir: dirname(fileURLToPath(import.meta.url)), | ||
| }, | ||
| }, | ||
| }), | ||
| eslintPluginPrettierRecommended, | ||
| ]; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "type": "commonjs" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| { | ||
| "type": "module" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation of
messageHashCkbSuperiseis incorrect forBytesLikemessages. WhenmessageisBytesLike, it's converted to a hex string, and thenmsg.lengthis used. This uses the length of the hex string, not the byte length of the message. Additionally, the hex string itself is then encoded as UTF-8, which is not the standard way of hashing byte arrays.This will cause signature verification to fail for any non-string messages.
The implementation should be similar to
messageHashEvmPersonal, where the message is first converted to aUint8Arrayto get its byte length, and then the parts are concatenated as bytes.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msg.lengthhas different behavior across programming languages. Some use byte length, other might use character count. This might cause problem when developers use different programming languages to interact with SupeRISE wallet. Common pattern is to use byte length as in Bitcoin and Ethereum.