Skip to content

Commit 8da8c0f

Browse files
wa0x6eChaituVR
andauthored
feat: support starknet signature verification (#1032)
* chore: add tests for evm signature verification * fix: add types * chore: fix lint * chore: add typecheck * chore: add typecheck to CI * fix: fix typescript warnings * chore: fix typechecl CI * feat: add starknet message verification * fix: use a more generic starknet RPC provider * refactor: more better structure for verification module * chore: add more tests * refactor: code improvement * fix: convert signature to r,s ECDSA format * fix: fix starknet validation * chore: remove unused file * fix: improve typing * fix: slim down abi * chore: bump min supported node version to 16 * fix: fix CI issue with tslib * fix: consider empty starknet address as invalid * fix: use more robust starknet address detection * fix: add hashed types for starknet alias * fix: include StarknetDomain in hash * fix: add support for starknet hash for `getHash` * fix: add follow type with string address * fix: allow unfollow from starknet address * fix: remove useless typing * fix: add support for profile edition from starknet address * fix: add addressFormatter to utils * chore: code standard * fix: consider 0x address as valid evm address * fix: improve error message * fix: use address detection from utils * chore: add more tests * chore: add more tests * fix: add optional format type when formatting an address * fix: fix invalid default args definition * fix: better starknet address validation rules * chore: use testnet for E2E tests * chore: add more tests * refactor: move value to a constant * refactor: better naming and types * refactor: better typing * refactor: better types * chore: add more tests * refactor: remove redundant types * fix: named exports functions * fix: update to use named export * Update src/verify/starknet.ts * lint * fix: use message payload instead of address to detect starknet message * refactor: code shortening * v0.12.0-beta.1 * Update src/utils.ts Co-authored-by: Chaitanya <[email protected]> * fix: format should only accept a single value * v0.12.0-beta.2 * v0.12.0-beta.3 * 0.12.0-beta.4 * fix: fix types file not found * Update package.json * fix: add `statement` hashType with starknet support * fix: use strict evm and starknet address validation * Update package.json --------- Co-authored-by: Chaitanya <[email protected]>
1 parent 9cea3f5 commit 8da8c0f

21 files changed

+772
-102
lines changed

.github/workflows/npm-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- uses: actions/checkout@v2
1515
- uses: actions/setup-node@v2
1616
with:
17-
node-version: 14
17+
node-version: 16
1818
registry-url: https://registry.npmjs.org/
1919
- run: yarn install --frozen-lockfile
2020
- run: npm publish

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88

99
strategy:
1010
matrix:
11-
node-version: ['14', '20']
11+
node-version: ['16', '20']
1212

1313
steps:
1414
- uses: actions/checkout@v3

.github/workflows/typecheck.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
name: Typecheck
2+
3+
on: [push]
4+
5+
jobs:
6+
typecheck:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v2
10+
- uses: actions/setup-node@v1
11+
with:
12+
node-version: '16.x'
13+
- name: Yarn install
14+
run: yarn install --frozen-lockfile
15+
- name: Typecheck
16+
run: yarn typecheck

.github/workflows/update-minor-version.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ jobs:
99
steps:
1010
- uses: actions/checkout@v2
1111
- uses: actions/setup-node@v1
12-
12+
1313
with:
14-
node-version: '14.x'
14+
node-version: '16.x'
1515
- name: Update minor
1616
run: |
1717
npm --no-git-tag-version version patch
@@ -22,6 +22,6 @@ jobs:
2222
title: Update minor version
2323
body: |
2424
- Update minor version in package.json
25-
25+
2626
Auto-generated by Github Actions
2727
branch: update-minor-version

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"name": "@snapshot-labs/snapshot.js",
3-
"version": "0.11.41",
3+
"version": "0.12.0",
44
"repository": "snapshot-labs/snapshot.js",
55
"license": "MIT",
66
"main": "dist/snapshot.cjs.js",
77
"module": "dist/snapshot.esm.js",
88
"browser": "dist/snapshot.min.js",
9-
"types": "dist/index.d.ts",
9+
"types": "dist/src/index.d.ts",
1010
"dependencies": {
1111
"@ensdomains/eth-ens-namehash": "^2.0.15",
1212
"@ethersproject/abi": "^5.6.4",
@@ -22,7 +22,8 @@
2222
"ajv-formats": "^2.1.1",
2323
"cross-fetch": "^3.1.6",
2424
"json-to-graphql-query": "^2.2.4",
25-
"lodash.set": "^4.3.2"
25+
"lodash.set": "^4.3.2",
26+
"starknet": "^5.24.3"
2627
},
2728
"devDependencies": {
2829
"@rollup/plugin-commonjs": "^18.1.0",
@@ -60,7 +61,7 @@
6061
"prepublishOnly": "yarn build"
6162
},
6263
"engines": {
63-
"node": ">=14"
64+
"node": ">=16"
6465
},
6566
"files": [
6667
"dist",

src/sign/eip1271.ts

Lines changed: 0 additions & 55 deletions
This file was deleted.

src/sign/hashedTypes.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,10 @@
5555
"daaf0ff7d3e2ec189cf851228c386c7a4c432076d0ed197864916dd3f656531c": "subscribe",
5656
"f542edb6f9fe79d0b85554667991352be2fcca85df3dd3c6a6f451d189c7c25d": "unsubscribe",
5757
"6f6cdd15a1e9e6c4ee544231c4fa7b6c7e5183bc2b37fa4bd1a695f458348ab7": "delete-space",
58-
"1aad7825b991457fca04aae48a2a49d815ada524e10316af0da5522ea48b3df6": "alias"
58+
"1aad7825b991457fca04aae48a2a49d815ada524e10316af0da5522ea48b3df6": "alias",
59+
"8ea9074bff3a30cb61f4f0f0f142c9335c6be828feba0571a45de3f1fd0319c0": "alias",
60+
"42f8858a21d4aa232721cb97074851e729829ea362b88bb21f3879899663b586": "follow",
61+
"2bb75450e28b06f259ea764cd669de6bde0ba70ce729b0ff05ab9df56e0ff21d": "unfollow",
62+
"2ffbebcbd22ef48fd2f4a1182ff1feda7795b57689bd6f0dd73c89e925e7fefb": "profile",
63+
"4288d50b713081aae77d60d596d75864bff7acf7791a00183401e58658ee9da5": "statement"
5964
}

src/sign/utils.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/utils.spec.js

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
import { describe, test, expect, vi, afterEach } from 'vitest';
22
import * as crossFetch from 'cross-fetch';
3-
import { validate, getScores, getVp } from './utils';
3+
import {
4+
validate,
5+
validateSchema,
6+
getScores,
7+
getVp,
8+
getFormattedAddress
9+
} from './utils';
410

511
vi.mock('cross-fetch', async () => {
612
const actual = await vi.importActual('cross-fetch');
@@ -492,4 +498,117 @@ describe('utils', () => {
492498
});
493499
});
494500
});
501+
502+
describe('getFormattedAddress', () => {
503+
test('returns a checksummed EVM address', () => {
504+
const address = '0x91fd2c8d24767db4ece7069aa27832ffaf8590f3';
505+
expect(getFormattedAddress(address, 'evm')).toEqual(
506+
'0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
507+
);
508+
});
509+
510+
test('returns a padded and lowercased starknet address', () => {
511+
const address =
512+
'0x2a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0';
513+
expect(getFormattedAddress(address, 'starknet')).toEqual(
514+
'0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
515+
);
516+
});
517+
518+
test('returns an EVM address as starknet address', () => {
519+
const address = '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3';
520+
expect(getFormattedAddress(address, 'starknet')).toEqual(
521+
'0x00000000000000000000000091fd2c8d24767db4ece7069aa27832ffaf8590f3'
522+
);
523+
});
524+
525+
test('throws an error when the address is not a starknet address', () => {
526+
const address = 'hello';
527+
expect(() => getFormattedAddress(address, 'starknet')).toThrow();
528+
});
529+
530+
test('throws an error when the address is not an EVM address', () => {
531+
const address =
532+
'0x2a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0';
533+
expect(() => getFormattedAddress(address, 'evm')).toThrow();
534+
});
535+
});
536+
537+
describe('address validation', () => {
538+
const evmSchema = {
539+
$schema: 'http://json-schema.org/draft-07/schema#',
540+
$ref: '#/definitions/Envelope',
541+
definitions: {
542+
Envelope: {
543+
type: 'object',
544+
properties: {
545+
address: {
546+
type: 'string',
547+
format: 'address'
548+
}
549+
}
550+
}
551+
}
552+
};
553+
554+
const starknetSchema = {
555+
$schema: 'http://json-schema.org/draft-07/schema#',
556+
$ref: '#/definitions/Envelope',
557+
definitions: {
558+
Envelope: {
559+
type: 'object',
560+
properties: {
561+
address: {
562+
type: 'string',
563+
format: 'starknetAddress'
564+
}
565+
}
566+
}
567+
}
568+
};
569+
570+
test('should return true on checksummed EVM address', async () => {
571+
const result = validateSchema(evmSchema, {
572+
address: '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'
573+
});
574+
expect(result).toBe(true);
575+
});
576+
577+
test('should return an error on lowercase EVM address', async () => {
578+
const result = validateSchema(evmSchema, {
579+
address: '0x91FD2c8d24767db4Ece7069AA27832ffaf8590f3'.toLowerCase()
580+
});
581+
expect(result).not.toBe(true);
582+
});
583+
584+
test('should return an error on empty address', async () => {
585+
const result = validateSchema(evmSchema, {
586+
address: ''
587+
});
588+
expect(result).not.toBe(true);
589+
});
590+
591+
test('should return true on lowercase padded starknet address', async () => {
592+
const result = validateSchema(starknetSchema, {
593+
address:
594+
'0x02a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
595+
});
596+
expect(result).toBe(true);
597+
});
598+
599+
test('should return an error on non-padded starknet address', async () => {
600+
const result = validateSchema(starknetSchema, {
601+
address:
602+
'0x2a0a8f3b6097e7a6bd7649deb30715323072a159c0e6b71b689bd245c146cc0'
603+
});
604+
expect(result).not.toBe(true);
605+
});
606+
607+
test('should return an error on empty starknet address', async () => {
608+
const result = validateSchema(starknetSchema, {
609+
address: ''
610+
});
611+
expect(result).not.toBe(true);
612+
});
613+
});
495614
});

0 commit comments

Comments
 (0)