Repository: 0xs34n/starknet.js
Pull request #265 (2022-07-23 07:38:05)

One more v3 release


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e00271f6..b380776a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,21 @@
+## [3.18.2](https://github.com/0xs34n/starknet.js/compare/v3.18.1...v3.18.2) (2022-07-25)
+
+### Bug Fixes
+
+- release to [@next](https://github.com/next) ([12e37ce](https://github.com/0xs34n/starknet.js/commit/12e37cef78bc0e9d97d25c44d0dcf576969cb182))
+
+## [3.18.1](https://github.com/0xs34n/starknet.js/compare/v3.18.0...v3.18.1) (2022-07-23)
+
+### Bug Fixes
+
+- struct array hashing ([e1f82df](https://github.com/0xs34n/starknet.js/commit/e1f82dfd575be4c84b291c33f8169bf367493603))
+
+# [3.18.0](https://github.com/0xs34n/starknet.js/compare/v3.17.0...v3.18.0) (2022-07-23)
+
+### Features
+
+- **cairo-0.9.1:** starknet_version in block response ([e88154d](https://github.com/0xs34n/starknet.js/commit/e88154d5f6fcd6695dca5d29da04d18d0a65cdf6))
+
 # [3.17.0](https://github.com/0xs34n/starknet.js/compare/v3.16.3...v3.17.0) (2022-07-15)
 
 ### Features
diff --git a/README.md b/README.md
index 95daa65d..84b840ce 100644
--- a/README.md
+++ b/README.md
@@ -85,3 +85,4 @@ This library would not be possible without these rockstars.
 Copyright (c) 2022 0xs34n
 
 Licensed under the [MIT license](https://github.com/0xs34n/starknet.js/blob/main/LICENSE).
+
diff --git a/__mocks__/typedDataStructArrayExample.json b/__mocks__/typedDataStructArrayExample.json
new file mode 100644
index 00000000..fe4e6506
--- /dev/null
+++ b/__mocks__/typedDataStructArrayExample.json
@@ -0,0 +1,44 @@
+{
+  "types": {
+    "StarkNetDomain": [
+      { "name": "name", "type": "felt" },
+      { "name": "version", "type": "felt" },
+      { "name": "chainId", "type": "felt" }
+    ],
+    "Person": [
+      { "name": "name", "type": "felt" },
+      { "name": "wallet", "type": "felt" }
+    ],
+    "Post": [
+      { "name": "title", "type": "felt" },
+      { "name": "content", "type": "felt" }
+    ],
+    "Mail": [
+      { "name": "from", "type": "Person" },
+      { "name": "to", "type": "Person" },
+      { "name": "posts_len", "type": "felt" },
+      { "name": "posts", "type": "Post*" }
+    ]
+  },
+  "primaryType": "Mail",
+  "domain": {
+    "name": "StarkNet Mail",
+    "version": "1",
+    "chainId": 1
+  },
+  "message": {
+    "from": {
+      "name": "Cow",
+      "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"
+    },
+    "to": {
+      "name": "Bob",
+      "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"
+    },
+    "posts_len": 2,
+    "posts": [
+      { "title": "Greeting", "content": "Hello, Bob!" },
+      { "title": "Farewell", "content": "Goodbye, Bob!" }
+    ]
+  }
+}
diff --git a/package-lock.json b/package-lock.json
index 718e41e7..216675c5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "starknet",
-  "version": "3.17.0",
+  "version": "3.18.2",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "starknet",
-      "version": "3.17.0",
+      "version": "3.18.2",
       "license": "MIT",
       "dependencies": {
         "@ethersproject/bytes": "^5.6.1",
diff --git a/package.json b/package.json
index d669b0eb..2abad023 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "starknet",
-  "version": "3.17.0",
+  "version": "3.18.2",
   "description": "JavaScript library for StarkNet",
   "main": "dist/index.js",
   "types": "dist/index.d.ts",
diff --git a/src/provider/default.ts b/src/provider/default.ts
index 44ab8478..4a1cdd69 100644
--- a/src/provider/default.ts
+++ b/src/provider/default.ts
@@ -1,4 +1,5 @@
 import urljoin from 'url-join';
+import fetch from 'cross-fetch';
 
 import { ONE, StarknetChainId, ZERO } from '../constants';
 import {
diff --git a/src/types/api.ts b/src/types/api.ts
index 912c876b..682ebc95 100644
--- a/src/types/api.ts
+++ b/src/types/api.ts
@@ -195,6 +195,7 @@ export type GetBlockResponse = {
   parent_block_hash: string;
   status: Status;
   gas_price: string;
+  starknet_version?: string;
 };
 
 export type GetCodeResponse = {
diff --git a/src/utils/typedData/index.ts b/src/utils/typedData/index.ts
index 386e3a8a..fbde6ee4 100644
--- a/src/utils/typedData/index.ts
+++ b/src/utils/typedData/index.ts
@@ -36,6 +36,12 @@ export const getDependencies = (
     throw new Error('Typed data does not match JSON schema');
   }
 
+  // Include pointers (struct arrays)
+  if (type[type.length - 1] === '*') {
+    // eslint-disable-next-line no-param-reassign
+    type = type.slice(0, -1);
+  }
+
   if (dependencies.includes(type)) {
     return dependencies;
   }
@@ -102,6 +108,18 @@ const encodeValue = (typedData: TypedData, type: string, data: unknown): [string
     return [type, getStructHash(typedData, type, data as Record<string, unknown>)];
   }
 
+  if (
+    Object.keys(typedData.types)
+      .map((x) => `${x}*`)
+      .includes(type)
+  ) {
+    const structHashes: string[] = (data as unknown[]).map((struct) => {
+      // eslint-disable-next-line @typescript-eslint/no-use-before-define
+      return getStructHash(typedData, type.slice(0, -1), struct as Record<string, unknown>);
+    });
+    return [type, computeHashOnElements(structHashes)];
+  }
+
   if (type === 'felt*') {
     return ['felt*', computeHashOnElements(data as string[])];
   }
diff --git a/www/docs/API/provider.md b/www/docs/API/provider.md
index fae77a3e..ece80071 100644
--- a/www/docs/API/provider.md
+++ b/www/docs/API/provider.md
@@ -85,6 +85,7 @@ Gets the block information.
   transation: Transaction[];
   timestamp: number;
   transaction_receipts: [];
+  starknet_version: string;
 }
 ```
 


Test patch:
diff --git a/__tests__/utils/typedData.test.ts b/__tests__/utils/typedData.test.ts
index b59aed0d..30d52439 100644
--- a/__tests__/utils/typedData.test.ts
+++ b/__tests__/utils/typedData.test.ts
@@ -1,4 +1,5 @@
 import typedDataExample from '../../__mocks__/typedDataExample.json';
+import typedDataStructArrayExample from '../../__mocks__/typedDataStructArrayExample.json';
 import { number } from '../../src';
 import { BigNumberish } from '../../src/utils/number';
 import { encodeType, getMessageHash, getStructHash, getTypeHash } from '../../src/utils/typedData';
@@ -9,7 +10,12 @@ describe('typedData', () => {
     expect(typeEncoding).toMatchInlineSnapshot(
       `"Mail(from:Person,to:Person,contents:felt)Person(name:felt,wallet:felt)"`
     );
+    const typeEncodingStructArr = encodeType(typedDataStructArrayExample, 'Mail');
+    expect(typeEncodingStructArr).toMatchInlineSnapshot(
+      `"Mail(from:Person,to:Person,posts_len:felt,posts:Post*)Person(name:felt,wallet:felt)Post(title:felt,content:felt)"`
+    );
   });
+
   test('should get right type hash', () => {
     const typeHashDomain = getTypeHash(typedDataExample, 'StarkNetDomain');
     expect(typeHashDomain).toMatchInlineSnapshot(
@@ -23,18 +29,36 @@ describe('typedData', () => {
     expect(typeHashMail).toMatchInlineSnapshot(
       `"0x13d89452df9512bf750f539ba3001b945576243288137ddb6c788457d4b2f79"`
     );
+    const typeHashPost = getTypeHash(typedDataStructArrayExample, 'Post');
+    expect(typeHashPost).toMatchInlineSnapshot(
+      `"0x1d71e69bf476486b43cdcfaf5a85c00bb2d954c042b281040e513080388356d"`
+    );
+    const typeHashMailWithStructArray = getTypeHash(typedDataStructArrayExample, 'Mail');
+    expect(typeHashMailWithStructArray).toMatchInlineSnapshot(
+      `"0x873b878e35e258fc99e3085d5aaad3a81a0c821f189c08b30def2cde55ff27"`
+    );
   });
+
   test('should get right hash for StarkNetDomain', () => {
     const hash = getStructHash(typedDataExample, 'StarkNetDomain', typedDataExample.domain as any);
     expect(hash).toMatchInlineSnapshot(
       `"0x54833b121883a3e3aebff48ec08a962f5742e5f7b973469c1f8f4f55d470b07"`
     );
   });
+
   test('should get right hash for entire message', () => {
     const hash = getMessageHash(typedDataExample, '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826');
     expect(hash).toMatchInlineSnapshot(
       `"0x6fcff244f63e38b9d88b9e3378d44757710d1b244282b435cb472053c8d78d0"`
     );
+
+    const hashStructArr = getMessageHash(
+      typedDataStructArrayExample,
+      '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826'
+    );
+    expect(hashStructArr).toMatchInlineSnapshot(
+      `"0x5914ed2764eca2e6a41eb037feefd3d2e33d9af6225a9e7fe31ac943ff712c"`
+    );
   });
 
   interface StringStruct {