From 16fb61875222113ef208897c44415ef17faa291a Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 26 Apr 2023 17:47:18 +0200
Subject: [PATCH 01/98] bump nucypher-core to 0.6.0
---
package.json | 2 +-
src/characters/bob.ts | 4 +-
src/characters/porter.ts | 10 +++--
src/characters/universal-bob.ts | 13 +++---
src/keyring.ts | 2 +-
src/policies/policy.ts | 2 +-
src/sdk/strategy.ts | 22 +++++-----
test/acceptance/alice-grants.test.ts | 21 ++++++++--
test/acceptance/delay-enact.test.ts | 2 +-
test/docs/cbd.test.ts | 2 +-
test/integration/conditions.test.ts | 2 +-
test/integration/enrico.test.ts | 4 +-
test/unit/strategy.test.ts | 24 +++++------
test/unit/testVariables.ts | 60 ++++++++++++++++++++++++----
test/utils.ts | 8 ++--
yarn.lock | 8 ++--
16 files changed, 124 insertions(+), 62 deletions(-)
diff --git a/package.json b/package.json
index 7bcc725b3..eef0e6f90 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
"prebuild": "yarn typechain"
},
"dependencies": {
- "@nucypher/nucypher-core": "0.4.0",
+ "@nucypher/nucypher-core": "^0.6.0",
"axios": "^0.21.1",
"ethers": "^5.4.1",
"joi": "^17.7.0",
diff --git a/src/characters/bob.ts b/src/characters/bob.ts
index 5d4c67101..1ee8606af 100644
--- a/src/characters/bob.ts
+++ b/src/characters/bob.ts
@@ -27,11 +27,11 @@ export class RemoteBob {
const dk =
decryptingKey instanceof PublicKey
? decryptingKey
- : PublicKey.fromBytes(decryptingKey);
+ : PublicKey.fromCompressedBytes(decryptingKey);
const vk =
verifyingKey instanceof PublicKey
? verifyingKey
- : PublicKey.fromBytes(verifyingKey);
+ : PublicKey.fromCompressedBytes(verifyingKey);
return new RemoteBob(dk, vk);
}
}
diff --git a/src/characters/porter.ts b/src/characters/porter.ts
index 7834ab491..ee0df9a40 100644
--- a/src/characters/porter.ts
+++ b/src/characters/porter.ts
@@ -93,7 +93,9 @@ export class Porter {
return resp.data.result.ursulas.map((u: UrsulaResponse) => ({
checksumAddress: u.checksum_address,
uri: u.uri,
- encryptingKey: PublicKey.fromBytes(fromHexString(u.encrypting_key)),
+ encryptingKey: PublicKey.fromCompressedBytes(
+ fromHexString(u.encrypting_key)
+ ),
}));
}
@@ -111,9 +113,9 @@ export class Porter {
const data: PostRetrieveCFragsRequest = {
treasure_map: toBase64(treasureMap.toBytes()),
retrieval_kits: retrievalKits.map((rk) => toBase64(rk.toBytes())),
- alice_verifying_key: toHexString(aliceVerifyingKey.toBytes()),
- bob_encrypting_key: toHexString(bobEncryptingKey.toBytes()),
- bob_verifying_key: toHexString(bobVerifyingKey.toBytes()),
+ alice_verifying_key: toHexString(aliceVerifyingKey.toCompressedBytes()),
+ bob_encrypting_key: toHexString(bobEncryptingKey.toCompressedBytes()),
+ bob_verifying_key: toHexString(bobVerifyingKey.toCompressedBytes()),
context,
};
const resp: AxiosResponse = await axios.post(
diff --git a/src/characters/universal-bob.ts b/src/characters/universal-bob.ts
index be8b6afc6..3bdbb95d7 100644
--- a/src/characters/universal-bob.ts
+++ b/src/characters/universal-bob.ts
@@ -140,10 +140,11 @@ export class tDecDecrypter {
public toObj(): decrypterJSON {
return {
porterUri: this.porter.porterUrl.toString(),
- policyEncryptingKeyBytes: this.policyEncryptingKey.toBytes(),
+ policyEncryptingKeyBytes: this.policyEncryptingKey.toCompressedBytes(),
encryptedTreasureMapBytes: this.encryptedTreasureMap.toBytes(),
- publisherVerifyingKeyBytes: this.publisherVerifyingKey.toBytes(),
- bobSecretKeyBytes: this.keyring.secretKey.toSecretBytes(),
+ publisherVerifyingKeyBytes:
+ this.publisherVerifyingKey.toCompressedBytes(),
+ bobSecretKeyBytes: this.keyring.secretKey.toBEBytes(),
};
}
@@ -160,10 +161,10 @@ export class tDecDecrypter {
}: decrypterJSON) {
return new tDecDecrypter(
porterUri,
- PublicKey.fromBytes(policyEncryptingKeyBytes),
+ PublicKey.fromCompressedBytes(policyEncryptingKeyBytes),
EncryptedTreasureMap.fromBytes(encryptedTreasureMapBytes),
- PublicKey.fromBytes(publisherVerifyingKeyBytes),
- SecretKey.fromBytes(bobSecretKeyBytes)
+ PublicKey.fromCompressedBytes(publisherVerifyingKeyBytes),
+ SecretKey.fromBEBytes(bobSecretKeyBytes)
);
}
diff --git a/src/keyring.ts b/src/keyring.ts
index 4e0f06b99..4b769b95e 100644
--- a/src/keyring.ts
+++ b/src/keyring.ts
@@ -55,7 +55,7 @@ export class Keyring {
private getSecretKeyFromLabel(label: string): SecretKey {
return SecretKeyFactory.fromSecureRandomness(
- this.secretKey.toSecretBytes()
+ this.secretKey.toBEBytes()
).makeKey(toBytes(label));
}
diff --git a/src/policies/policy.ts b/src/policies/policy.ts
index 54d95719e..dbb23eccb 100644
--- a/src/policies/policy.ts
+++ b/src/policies/policy.ts
@@ -131,7 +131,7 @@ export class BlockchainPolicy {
this.delegatingKey,
encryptedTreasureMap,
// revocationKit,
- this.publisher.verifyingKey.toBytes(),
+ this.publisher.verifyingKey.toCompressedBytes(),
this.shares,
this.startDate,
this.endDate
diff --git a/src/sdk/strategy.ts b/src/sdk/strategy.ts
index 15190f8b8..490e44d57 100644
--- a/src/sdk/strategy.ts
+++ b/src/sdk/strategy.ts
@@ -136,8 +136,8 @@ export class Strategy {
}: StrategyJSON) {
return new Strategy(
Cohort.fromObj(cohort),
- SecretKey.fromBytes(aliceSecretKeyBytes),
- SecretKey.fromBytes(bobSecretKeyBytes),
+ SecretKey.fromBEBytes(aliceSecretKeyBytes),
+ SecretKey.fromBEBytes(bobSecretKeyBytes),
startDate,
endDate,
conditionSet
@@ -147,8 +147,8 @@ export class Strategy {
public toObj(): StrategyJSON {
return {
cohort: this.cohort.toObj(),
- aliceSecretKeyBytes: this.aliceSecretKey.toSecretBytes(),
- bobSecretKeyBytes: this.bobSecretKey.toSecretBytes(),
+ aliceSecretKeyBytes: this.aliceSecretKey.toBEBytes(),
+ bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
conditionSet: this.conditionSet,
startDate: this.startDate,
endDate: this.endDate,
@@ -183,23 +183,25 @@ export class DeployedStrategy {
conditionSet,
}: DeployedStrategyJSON) {
const id = HRAC.fromBytes(policy.id);
- const policyKey = PublicKey.fromBytes(policy.policyKey);
+ const policyKey = PublicKey.fromCompressedBytes(policy.policyKey);
const encryptedTreasureMap = EncryptedTreasureMap.fromBytes(
policy.encryptedTreasureMap
);
- const aliceVerifyingKey = PublicKey.fromBytes(policy.aliceVerifyingKey);
+ const aliceVerifyingKey = PublicKey.fromCompressedBytes(
+ policy.aliceVerifyingKey
+ );
const newPolicy = {
id,
label: policy.label,
policyKey,
encryptedTreasureMap,
- aliceVerifyingKey: aliceVerifyingKey.toBytes(),
+ aliceVerifyingKey: aliceVerifyingKey.toCompressedBytes(),
size: policy.size,
startTimestamp: policy.startTimestamp,
endTimestamp: policy.endTimestamp,
txHash: policy.txHash,
};
- const bobSecretKey = SecretKey.fromBytes(bobSecretKeyBytes);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
const label = newPolicy.label;
const cohort = Cohort.fromObj(cohortConfig);
const encrypter = new Enrico(newPolicy.policyKey, undefined, conditionSet);
@@ -226,13 +228,13 @@ export class DeployedStrategy {
const policy = {
...this.policy,
id: this.policy.id.toBytes(),
- policyKey: this.policy.policyKey.toBytes(),
+ policyKey: this.policy.policyKey.toCompressedBytes(),
encryptedTreasureMap: this.policy.encryptedTreasureMap.toBytes(),
};
return {
policy,
cohortConfig: this.cohort.toObj(),
- bobSecretKeyBytes: this.bobSecretKey.toSecretBytes(),
+ bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
conditionSet: this.conditionSet,
};
}
diff --git a/test/acceptance/alice-grants.test.ts b/test/acceptance/alice-grants.test.ts
index 3e1f661aa..8ccf532fc 100644
--- a/test/acceptance/alice-grants.test.ts
+++ b/test/acceptance/alice-grants.test.ts
@@ -64,7 +64,9 @@ describe('story: alice shares message with bob through policy', () => {
};
policy = await alice.grant(policyParams);
- expect(policy.aliceVerifyingKey).toEqual(alice.verifyingKey.toBytes());
+ expect(policy.aliceVerifyingKey).toEqual(
+ alice.verifyingKey.toCompressedBytes()
+ );
expect(policy.label).toBe(label);
expect(getUrsulasSpy).toHaveBeenCalled();
expect(generateKFragsSpy).toHaveBeenCalled();
@@ -121,12 +123,23 @@ describe('story: alice shares message with bob through policy', () => {
bobVerifyingKey_,
] = retrieveCFragsSpy.mock.calls[0];
expect(
- bytesEqual(aliceVerifyingKey_.toBytes(), aliceVerifyingKey.toBytes())
+ bytesEqual(
+ aliceVerifyingKey_.toCompressedBytes(),
+ aliceVerifyingKey.toCompressedBytes()
+ )
+ );
+ expect(
+ bytesEqual(
+ bobEncryptingKey_.toCompressedBytes(),
+ bob.decryptingKey.toCompressedBytes()
+ )
);
expect(
- bytesEqual(bobEncryptingKey_.toBytes(), bob.decryptingKey.toBytes())
+ bytesEqual(
+ bobVerifyingKey_.toCompressedBytes(),
+ bob.verifyingKey.toCompressedBytes()
+ )
);
- expect(bytesEqual(bobVerifyingKey_.toBytes(), bob.verifyingKey.toBytes()));
const { verifiedCFrags } = reencryptKFrags(
verifiedKFrags,
diff --git a/test/acceptance/delay-enact.test.ts b/test/acceptance/delay-enact.test.ts
index 6ca4cc623..9e76b7d5a 100644
--- a/test/acceptance/delay-enact.test.ts
+++ b/test/acceptance/delay-enact.test.ts
@@ -38,7 +38,7 @@ describe('story: alice1 creates a policy but alice2 enacts it', () => {
policyParams
);
expect(preEnactedPolicy.aliceVerifyingKey).toEqual(
- alice1.verifyingKey.toBytes()
+ alice1.verifyingKey.toCompressedBytes()
);
expect(preEnactedPolicy.label).toBe(label);
diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts
index 650ad1f2f..79fb91b4e 100644
--- a/test/docs/cbd.test.ts
+++ b/test/docs/cbd.test.ts
@@ -52,7 +52,7 @@ describe('Get Started (CBD PoC)', () => {
jest
.spyOn(providers, 'Web3Provider')
.mockImplementation(() =>
- mockWeb3Provider(SecretKey.random().toSecretBytes())
+ mockWeb3Provider(SecretKey.random().toBEBytes())
);
//
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index 5fe41aa84..373a2d54e 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -239,7 +239,7 @@ describe('produce context parameters from conditions', () => {
describe('condition context', () => {
it('should serialize to JSON with context params', async () => {
- const web3Provider = mockWeb3Provider(SecretKey.random().toSecretBytes());
+ const web3Provider = mockWeb3Provider(SecretKey.random().toBEBytes());
const rpcCondition = new Conditions.RpcCondition({
chain: 5,
diff --git a/test/integration/enrico.test.ts b/test/integration/enrico.test.ts
index f3281b0ad..fb57894c4 100644
--- a/test/integration/enrico.test.ts
+++ b/test/integration/enrico.test.ts
@@ -51,7 +51,9 @@ describe('enrico', () => {
threshold,
shares
);
- expect(delegatingKey.toBytes()).toEqual(policyEncryptingKey.toBytes());
+ expect(delegatingKey.toCompressedBytes()).toEqual(
+ policyEncryptingKey.toCompressedBytes()
+ );
// Bob can decrypt re-encrypted ciphertext
const { verifiedCFrags } = reencryptKFrags(
diff --git a/test/unit/strategy.test.ts b/test/unit/strategy.test.ts
index be450cc69..9c85c7ca0 100644
--- a/test/unit/strategy.test.ts
+++ b/test/unit/strategy.test.ts
@@ -40,9 +40,9 @@ describe('Strategy', () => {
shares: 3,
porterUri: 'https://_this.should.crash',
};
- const aliceSecretKey = SecretKey.fromBytes(aliceSecretKeyBytes);
- const bobSecretKey = SecretKey.fromBytes(bobSecretKeyBytes);
- const aliceProvider = mockWeb3Provider(aliceSecretKey.toSecretBytes());
+ const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
+ const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
Date.now = jest.fn(() => 1487076708000);
afterEach(() => {
@@ -120,15 +120,15 @@ describe('Deployed Strategy', () => {
shares: 3,
porterUri: 'https://_this.should.crash',
};
- const aliceSecretKey = SecretKey.fromBytes(aliceSecretKeyBytes);
- const bobSecretKey = SecretKey.fromBytes(bobSecretKeyBytes);
+ const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
afterEach(() => {
jest.clearAllMocks();
});
it('can export to JSON', async () => {
- const aliceProvider = mockWeb3Provider(aliceSecretKey.toSecretBytes());
+ const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
const mockedUrsulas = mockUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
@@ -163,8 +163,8 @@ describe('Deployed Strategy', () => {
});
it('can encrypt and decrypt', async () => {
- const aliceProvider = mockWeb3Provider(aliceSecretKey.toSecretBytes());
- const bobProvider = mockWeb3Provider(bobSecretKey.toSecretBytes());
+ const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
+ const bobProvider = mockWeb3Provider(bobSecretKey.toBEBytes());
const mockedUrsulas = mockUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
@@ -195,11 +195,10 @@ describe('Deployed Strategy', () => {
parameters: [3591],
chain: 5,
});
-
const plaintext = 'this is a secret';
- const conditions = new ConditionSet([ownsNFT]);
- encrypter.conditions = conditions;
+ encrypter.conditions = new ConditionSet([ownsNFT]);
const encryptedMessageKit = encrypter.encryptMessage(plaintext);
+
// Setup mocks for `retrieveAndDecrypt`
const getUrsulasSpy2 = mockGetUrsulas(mockedUrsulas);
const ursulaAddresses = (
@@ -227,8 +226,7 @@ describe('tDecDecrypter', () => {
const importedStrategy = DeployedStrategy.fromJSON(deployedStrategyJSON);
it('can export to JSON', () => {
- const decrypter = importedStrategy.decrypter;
- const configJSON = decrypter.toJSON();
+ const configJSON = importedStrategy.decrypter.toJSON();
expect(configJSON).toEqual(decrypterJSON);
});
diff --git a/test/unit/testVariables.ts b/test/unit/testVariables.ts
index 643c853c9..bc315b18c 100644
--- a/test/unit/testVariables.ts
+++ b/test/unit/testVariables.ts
@@ -1,12 +1,48 @@
-export const strategyJSON =
- '{"cohort":{"ursulaAddresses":["0x5cf1703a1c99a4b42eb056535840e93118177232","0x7fff551249d223f723557a96a0e1a469c79cc934","0x9c7c824239d3159327024459ad69bb215859bd25"],"threshold":2,"shares":3,"porterUri":"https://_this.should.crash"},"aliceSecretKeyBytes":"base64:N1K+vcukPJQkVi57P5jXca5W9CwX48VEBVV0H9CYWDU=","bobSecretKeyBytes":"base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=","startDate":"2017-02-14T12:51:48.000Z","endDate":"2017-03-16T12:51:48.000Z"}';
+export const strategyJSON = JSON.stringify({
+ cohort: {
+ ursulaAddresses: [
+ '0x5cf1703a1c99a4b42eb056535840e93118177232',
+ '0x7fff551249d223f723557a96a0e1a469c79cc934',
+ '0x9c7c824239d3159327024459ad69bb215859bd25',
+ ],
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ },
+ aliceSecretKeyBytes: 'base64:N1K+vcukPJQkVi57P5jXca5W9CwX48VEBVV0H9CYWDU=',
+ bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
+ startDate: '2017-02-14T12:51:48.000Z',
+ endDate: '2017-03-16T12:51:48.000Z',
+});
export const encryptedTreasureMapBase64 =
- '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';
-
-export const deployedStrategyJSON =
- '{"policy":{"id":"base64:tKuR/HipMeU4trCdytbZCQ==","label":"test","policyKey":"base64:A/u/2+G8Hn0UPwRZqVfa41XiT/6W2+98dotTob7xKg5C","encryptedTreasureMap":"base64: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","aliceVerifyingKey":"base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj","size":3,"startTimestamp":"2017-02-14T12:51:48.000Z","endTimestamp":"2017-03-16T12:51:48.000Z","txHash":"0x1234567890123456789012345678901234567890"},"cohortConfig":{"ursulaAddresses":["0x5cf1703a1c99a4b42eb056535840e93118177232","0x7fff551249d223f723557a96a0e1a469c79cc934","0x9c7c824239d3159327024459ad69bb215859bd25"],"threshold":2,"shares":3,"porterUri":"https://_this.should.crash"},"bobSecretKeyBytes":"base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk="}';
+ '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';
+export const deployedStrategyJSON = JSON.stringify({
+ policy: {
+ id: 'base64:tKuR/HipMeU4trCdytbZCQ==',
+ label: 'test',
+ policyKey: 'base64:A/u/2+G8Hn0UPwRZqVfa41XiT/6W2+98dotTob7xKg5C',
+ encryptedTreasureMap:
+ 'base64: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',
+ aliceVerifyingKey: 'base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj',
+ size: 3,
+ startTimestamp: '2017-02-14T12:51:48.000Z',
+ endTimestamp: '2017-03-16T12:51:48.000Z',
+ txHash: '0x1234567890123456789012345678901234567890',
+ },
+ cohortConfig: {
+ ursulaAddresses: [
+ '0x5cf1703a1c99a4b42eb056535840e93118177232',
+ '0x7fff551249d223f723557a96a0e1a469c79cc934',
+ '0x9c7c824239d3159327024459ad69bb215859bd25',
+ ],
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ },
+ bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
+});
export const aliceSecretKeyBytes = new Uint8Array([
55, 82, 190, 189, 203, 164, 60, 148, 36, 86, 46, 123, 63, 152, 215, 113, 174,
86, 244, 44, 23, 227, 197, 68, 5, 85, 116, 31, 208, 152, 88, 53,
@@ -17,5 +53,13 @@ export const bobSecretKeyBytes = new Uint8Array([
229, 2, 106, 176, 205, 33, 168, 23, 213, 233, 200, 238, 11, 193, 153,
]);
-export const decrypterJSON =
- '{"porterUri":"https://_this.should.crash/","policyEncryptingKeyBytes":"base64:A/u/2+G8Hn0UPwRZqVfa41XiT/6W2+98dotTob7xKg5C","encryptedTreasureMapBytes":"base64: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","publisherVerifyingKeyBytes":"base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj","bobSecretKeyBytes":"base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk="}';
+export const decrypterJSON = JSON.stringify({
+ porterUri: 'https://_this.should.crash/',
+ policyEncryptingKeyBytes:
+ 'base64:A/u/2+G8Hn0UPwRZqVfa41XiT/6W2+98dotTob7xKg5C',
+ encryptedTreasureMapBytes:
+ 'base64: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',
+ publisherVerifyingKeyBytes:
+ 'base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj',
+ bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
+});
diff --git a/test/utils.ts b/test/utils.ts
index c27b5da7b..13f0bb504 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -37,7 +37,7 @@ const mockConfig: Configuration = {
};
export const mockBob = (): Bob => {
- const secretKey = SecretKey.fromBytes(
+ const secretKey = SecretKey.fromBEBytes(
toBytes('fake-secret-key-32-bytes-bob-xxx')
);
return Bob.fromSecretKey(mockConfig, secretKey);
@@ -49,8 +49,8 @@ export const mockRemoteBob = (): RemoteBob => {
};
export const mockAlice = (aliceKey = 'fake-secret-key-32-bytes-alice-x') => {
- const secretKey = SecretKey.fromBytes(toBytes(aliceKey));
- const provider = mockWeb3Provider(secretKey.toSecretBytes());
+ const secretKey = SecretKey.fromBEBytes(toBytes(aliceKey));
+ const provider = mockWeb3Provider(secretKey.toBEBytes());
return Alice.fromSecretKey(mockConfig, secretKey, provider);
};
@@ -123,7 +123,7 @@ export const mockGetUrsulas = (ursulas: readonly Ursula[]) => {
return {
result: {
ursulas: mockUrsulas.map(({ encryptingKey, uri, checksumAddress }) => ({
- encrypting_key: toHexString(encryptingKey.toBytes()),
+ encrypting_key: toHexString(encryptingKey.toCompressedBytes()),
uri: uri,
checksum_address: checksumAddress,
})),
diff --git a/yarn.lock b/yarn.lock
index bf7e3e148..30f8d5744 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1643,10 +1643,10 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
-"@nucypher/nucypher-core@0.4.0":
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/@nucypher/nucypher-core/-/nucypher-core-0.4.0.tgz#1388abde9de61ed848959b86bc96e3d12ef97ae4"
- integrity sha512-Pu4tRCwf7lnhZSoMjp889uTIUM7bNmYEe05TOOCuMYbJKmQWe7tYKeH0+rflUBISzGtMx2+xDe2CYYTyEGkvSw==
+"@nucypher/nucypher-core@^0.6.0":
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/@nucypher/nucypher-core/-/nucypher-core-0.6.0.tgz#07f60e2ba084efe3174afa7eefcb75ba58a0ba39"
+ integrity sha512-6S+x3J8vTrcXowtPl0GtprF7WgyP3lsSSG3+AYJXS17Sz9n2UeUdfWIxXrXt4bPj27w0sfgwYfXDoVhS/DP68A==
"@sideway/address@^4.1.3":
version "4.1.4"
From ddde9940cea9f36059d0ba7923aebcd86ca12cc7 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 3 May 2023 12:05:03 +0200
Subject: [PATCH 02/98] fix leaking mocks
---
README.md | 7 +++---
package.json | 2 +-
test/acceptance/alice-grants.test.ts | 4 ++--
test/acceptance/delay-enact.test.ts | 4 ++--
test/docs/cbd.test.ts | 6 ++---
test/integration/pre.test.ts | 4 ++--
test/unit/cohort.test.ts | 10 ++++-----
test/unit/strategy.test.ts | 33 ++++++++++++++++------------
test/unit/testVariables.ts | 4 ++--
test/utils.ts | 19 +++++++++-------
10 files changed, 51 insertions(+), 42 deletions(-)
diff --git a/README.md b/README.md
index 5cd089265..c85ae1b19 100644
--- a/README.md
+++ b/README.md
@@ -7,9 +7,9 @@ Full documentation can be found [here](https://docs.threshold.network/app-develo
> **Warning**
>
> `nucypher-ts` is under [active development](https://github.com/nucypher/nucypher-ts/pulls):
->
-> - SDK does not support policy revocation.
-> - We expect breaking changes.
+>
+> - SDK does not support policy revocation.
+> - We expect breaking changes.
## Installation
@@ -26,6 +26,7 @@ To learn more, follow the tutorial at Threshold Network's [docs](https://docs.th
See [`nucypher-ts/examples`](https://github.com/nucypher/nucypher-ts/tree/main/examples) to find out how to integrate `nucypher-ts` into your favorite web framework.
We also provide two code samples of TAC applications:
+
- [nucypher/tdec-sandbox](https://github.com/nucypher/tdec-sandbox)
- [nucypher/tdec-nft-example](https://github.com/nucypher/tdec-nft-example)
diff --git a/package.json b/package.json
index eef0e6f90..bfa464554 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
"test:lint": "eslint src test --ext .ts",
"test:exports": "ts-unused-exports tsconfig.json --ignoreFiles src/index.ts",
"test:prettier": "prettier \"src/**/*.ts\" \"test/**/*.ts\" --list-different",
- "test:unit": "jest",
+ "test:unit": "jest --detectOpenHandles --forceExit --runInBand",
"watch:build": "tsc -p tsconfig.json -w",
"watch:test": "jest --watch",
"cov": "run-s build test:unit && open-cli coverage/index.html",
diff --git a/test/acceptance/alice-grants.test.ts b/test/acceptance/alice-grants.test.ts
index 8ccf532fc..f4414e2bb 100644
--- a/test/acceptance/alice-grants.test.ts
+++ b/test/acceptance/alice-grants.test.ts
@@ -12,6 +12,7 @@ import { toBytes } from '../../src/utils';
import {
bytesEqual,
fromBytes,
+ makeTestUrsulas,
mockAlice,
mockBob,
mockEncryptTreasureMap,
@@ -21,7 +22,6 @@ import {
mockPublishToBlockchain,
mockRemoteBob,
mockRetrieveCFragsRequest,
- mockUrsulas,
reencryptKFrags,
} from '../utils';
@@ -31,7 +31,7 @@ describe('story: alice shares message with bob through policy', () => {
const shares = 3;
const startDate = new Date();
const endDate = new Date(Date.now() + 60 * 1000);
- const mockedUrsulas = mockUrsulas().slice(0, shares);
+ const mockedUrsulas = makeTestUrsulas().slice(0, shares);
// Intermediate variables used for mocking
let encryptedTreasureMap: EncryptedTreasureMap;
diff --git a/test/acceptance/delay-enact.test.ts b/test/acceptance/delay-enact.test.ts
index 9e76b7d5a..151719f6f 100644
--- a/test/acceptance/delay-enact.test.ts
+++ b/test/acceptance/delay-enact.test.ts
@@ -1,11 +1,11 @@
import {
+ makeTestUrsulas,
mockAlice,
mockEncryptTreasureMap,
mockGenerateKFrags,
mockGetUrsulas,
mockPublishToBlockchain,
mockRemoteBob,
- mockUrsulas,
} from '../utils';
describe('story: alice1 creates a policy but alice2 enacts it', () => {
@@ -13,7 +13,7 @@ describe('story: alice1 creates a policy but alice2 enacts it', () => {
const shares = 3;
const startDate = new Date();
const endDate = new Date(Date.now() + 60 * 1000); // 60s later
- const mockedUrsulas = mockUrsulas().slice(0, shares);
+ const mockedUrsulas = makeTestUrsulas().slice(0, shares);
const label = 'fake-data-label';
it('alice generates a new policy', async () => {
diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts
index 79fb91b4e..956448355 100644
--- a/test/docs/cbd.test.ts
+++ b/test/docs/cbd.test.ts
@@ -11,6 +11,7 @@ import {
import { Ursula } from '../../src/characters/porter';
import { toBytes } from '../../src/utils';
import {
+ makeTestUrsulas,
mockDetectEthereumProvider,
mockEncryptTreasureMap,
mockGenerateKFrags,
@@ -18,7 +19,6 @@ import {
mockMakeTreasureMap,
mockPublishToBlockchain,
mockRetrieveCFragsRequest,
- mockUrsulas,
mockWeb3Provider,
} from '../utils';
@@ -42,7 +42,7 @@ describe('Get Started (CBD PoC)', () => {
it('can run the get started example', async () => {
const detectEthereumProvider = mockDetectEthereumProvider();
- const mockedUrsulas = mockUrsulas();
+ const mockedUrsulas = makeTestUrsulas();
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -126,7 +126,7 @@ describe('Get Started (CBD PoC)', () => {
// End of the code example
//
- const expectedAddresses = mockUrsulas().map((u) => u.checksumAddress);
+ const expectedAddresses = makeTestUrsulas().map((u) => u.checksumAddress);
const condObj = conditions.conditions[0].toObj();
expect(newCohort.ursulaAddresses).toEqual(expectedAddresses);
expect(condObj.parameters).toEqual([5954]);
diff --git a/test/integration/pre.test.ts b/test/integration/pre.test.ts
index c896c7b6c..b5bf3c311 100644
--- a/test/integration/pre.test.ts
+++ b/test/integration/pre.test.ts
@@ -10,13 +10,13 @@ import {
} from '../../src';
import { RetrievalResult } from '../../src/kits/retrieval';
import { toBytes, zip } from '../../src/utils';
-import { mockAlice, mockBob, mockUrsulas, reencryptKFrags } from '../utils';
+import { makeTestUrsulas, mockAlice, mockBob, reencryptKFrags } from '../utils';
describe('proxy reencryption', () => {
const plaintext = toBytes('plaintext-message');
const threshold = 2;
const shares = 3;
- const ursulas = mockUrsulas().slice(0, shares);
+ const ursulas = makeTestUrsulas().slice(0, shares);
const label = 'fake-data-label';
const alice = mockAlice();
const bob = mockBob();
diff --git a/test/unit/cohort.test.ts b/test/unit/cohort.test.ts
index 54ed84457..7cfd66eea 100644
--- a/test/unit/cohort.test.ts
+++ b/test/unit/cohort.test.ts
@@ -1,9 +1,9 @@
-import { Cohort } from '../../src/sdk/cohort';
-import { mockGetUrsulas, mockUrsulas } from '../utils';
+import { Cohort } from '../../src';
+import { makeTestUrsulas, mockGetUrsulas } from '../utils';
describe('Cohort', () => {
it('can create Cohort from configuration', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const config = {
@@ -23,7 +23,7 @@ describe('Cohort', () => {
});
it('can export to JSON', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const config = {
threshold: 2,
@@ -39,7 +39,7 @@ describe('Cohort', () => {
});
it('can import from JSON', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const configJSON =
diff --git a/test/unit/strategy.test.ts b/test/unit/strategy.test.ts
index 9c85c7ca0..38ada25b3 100644
--- a/test/unit/strategy.test.ts
+++ b/test/unit/strategy.test.ts
@@ -15,13 +15,13 @@ import {
import { Ursula } from '../../src/characters/porter';
import { fromBase64, toBytes } from '../../src/utils';
import {
+ makeTestUrsulas,
mockEncryptTreasureMap,
mockGenerateKFrags,
mockGetUrsulas,
mockMakeTreasureMap,
mockPublishToBlockchain,
mockRetrieveCFragsRequest,
- mockUrsulas,
mockWeb3Provider,
} from '../utils';
@@ -46,11 +46,11 @@ describe('Strategy', () => {
Date.now = jest.fn(() => 1487076708000);
afterEach(() => {
- jest.clearAllMocks();
+ jest.restoreAllMocks();
});
it('can create Strategy from configuration', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const testCohort = await Cohort.create(cohortConfig);
@@ -61,26 +61,29 @@ describe('Strategy', () => {
bobSecretKey
);
- const expectedUrsulas = [
- '0x5cf1703a1c99a4b42eb056535840e93118177232',
- '0x7fff551249d223f723557a96a0e1a469c79cc934',
- '0x9c7c824239d3159327024459ad69bb215859bd25',
- ];
+ const expectedUrsulas = mockedUrsulas.map(
+ (ursula) => ursula.checksumAddress
+ );
expect(getUrsulasSpy).toHaveBeenCalled();
expect(testStrategy.cohort.ursulaAddresses).toEqual(expectedUrsulas);
});
it('can export to JSON', async () => {
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const testCohort = await Cohort.create(cohortConfig);
const testStrategy = Strategy.create(
testCohort,
undefined,
aliceSecretKey,
- bobSecretKey
+ bobSecretKey,
+ new Date('2017-02-14T12:51:48.000Z'),
+ new Date('2123-03-16T12:51:48.000Z')
);
const configJSON = testStrategy.toJSON();
expect(configJSON).toEqual(strategyJSON);
+ expect(getUrsulasSpy).toHaveBeenCalled();
});
it('can import from JSON', async () => {
@@ -94,7 +97,7 @@ describe('Strategy', () => {
});
it('can deploy and return DeployedStrategy', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -124,12 +127,12 @@ describe('Deployed Strategy', () => {
const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
afterEach(() => {
- jest.clearAllMocks();
+ jest.restoreAllMocks();
});
it('can export to JSON', async () => {
const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -143,7 +146,9 @@ describe('Deployed Strategy', () => {
testCohort,
undefined,
aliceSecretKey,
- bobSecretKey
+ bobSecretKey,
+ new Date('2017-02-14T12:51:48.000Z'),
+ new Date('2123-03-16T12:51:48.000Z')
);
const testDeployed = await testStrategy.deploy('test', aliceProvider);
expect(getUrsulasSpy).toHaveBeenCalled();
@@ -165,7 +170,7 @@ describe('Deployed Strategy', () => {
it('can encrypt and decrypt', async () => {
const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
const bobProvider = mockWeb3Provider(bobSecretKey.toBEBytes());
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
diff --git a/test/unit/testVariables.ts b/test/unit/testVariables.ts
index bc315b18c..34c1cc099 100644
--- a/test/unit/testVariables.ts
+++ b/test/unit/testVariables.ts
@@ -12,7 +12,7 @@ export const strategyJSON = JSON.stringify({
aliceSecretKeyBytes: 'base64:N1K+vcukPJQkVi57P5jXca5W9CwX48VEBVV0H9CYWDU=',
bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
startDate: '2017-02-14T12:51:48.000Z',
- endDate: '2017-03-16T12:51:48.000Z',
+ endDate: '2123-03-16T12:51:48.000Z',
});
export const encryptedTreasureMapBase64 =
@@ -28,7 +28,7 @@ export const deployedStrategyJSON = JSON.stringify({
aliceVerifyingKey: 'base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj',
size: 3,
startTimestamp: '2017-02-14T12:51:48.000Z',
- endTimestamp: '2017-03-16T12:51:48.000Z',
+ endTimestamp: '2123-03-16T12:51:48.000Z',
txHash: '0x1234567890123456789012345678901234567890',
},
cohortConfig: {
diff --git a/test/utils.ts b/test/utils.ts
index 13f0bb504..f4a0bac71 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -6,6 +6,7 @@ import {
Capsule,
CapsuleFrag,
EncryptedTreasureMap,
+ PublicKey,
reencrypt,
SecretKey,
VerifiedCapsuleFrag,
@@ -80,7 +81,7 @@ export const mockWeb3Provider = (
} as unknown as ethers.providers.Web3Provider;
};
-export const mockUrsulas = (): readonly Ursula[] => {
+export const makeTestUrsulas = (): readonly Ursula[] => {
return [
{
encryptingKey: SecretKey.random().publicKey(),
@@ -148,11 +149,6 @@ export const mockCFragResponse = (
verifiedKFrags: readonly VerifiedKeyFrag[],
capsule: Capsule
): readonly RetrieveCFragsResponse[] => {
- if (ursulas.length !== verifiedKFrags.length) {
- throw new Error(
- 'Number of verifiedKFrags must match the number of Ursulas'
- );
- }
const reencrypted = verifiedKFrags
.map((kFrag) => reencrypt(capsule, kFrag))
.map((cFrag) => CapsuleFrag.fromBytes(cFrag.toBytes()));
@@ -179,8 +175,15 @@ export const mockRetrieveCFragsRequestThrows = () => {
.mockRejectedValue(new Error('fake-reencryption-request-failed-error'));
};
-export const mockGenerateKFrags = () => {
- return jest.spyOn(Alice.prototype as any, 'generateKFrags');
+export const mockGenerateKFrags = (withValue?: {
+ delegatingKey: PublicKey;
+ verifiedKFrags: VerifiedKeyFrag[];
+}) => {
+ const spy = jest.spyOn(Alice.prototype as any, 'generateKFrags');
+ if (withValue) {
+ return spy.mockImplementation(() => withValue);
+ }
+ return spy;
};
export const mockEncryptTreasureMap = (withValue?: EncryptedTreasureMap) => {
From af6bba61161e962bb3e6414b0eb5901c00105f57 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 3 May 2023 12:15:49 +0200
Subject: [PATCH 03/98] bump nucypher-core to 0.7.0
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index bfa464554..23a48e6e2 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,7 @@
"prebuild": "yarn typechain"
},
"dependencies": {
- "@nucypher/nucypher-core": "^0.6.0",
+ "@nucypher/nucypher-core": "^0.7.0",
"axios": "^0.21.1",
"ethers": "^5.4.1",
"joi": "^17.7.0",
diff --git a/yarn.lock b/yarn.lock
index 30f8d5744..98cab979a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1643,10 +1643,10 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
-"@nucypher/nucypher-core@^0.6.0":
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/@nucypher/nucypher-core/-/nucypher-core-0.6.0.tgz#07f60e2ba084efe3174afa7eefcb75ba58a0ba39"
- integrity sha512-6S+x3J8vTrcXowtPl0GtprF7WgyP3lsSSG3+AYJXS17Sz9n2UeUdfWIxXrXt4bPj27w0sfgwYfXDoVhS/DP68A==
+"@nucypher/nucypher-core@^0.7.0":
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/@nucypher/nucypher-core/-/nucypher-core-0.7.0.tgz#2549364f39087a32be3abd8510baa45c1089d205"
+ integrity sha512-L8jDHIkEPgK4rPOwf7UkePGI/AHnP77TyE7iktO1G/bMGPZzsZ4YVg0Tw13T/3mPLEVjFOFZqA+h75wK3rHU6g==
"@sideway/address@^4.1.3":
version "4.1.4"
From 4c35dd69feb18a69dd8ba8014584cba8ac6c780f Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 3 May 2023 13:32:40 +0200
Subject: [PATCH 04/98] add ferveo-wasm to deps
---
package.json | 1 +
test/unit/ferveo-example.test.ts | 182 +++++++++++++++++++++++++++++++
yarn.lock | 5 +
3 files changed, 188 insertions(+)
create mode 100644 test/unit/ferveo-example.test.ts
diff --git a/package.json b/package.json
index 23a48e6e2..fc23a9f88 100644
--- a/package.json
+++ b/package.json
@@ -53,6 +53,7 @@
},
"dependencies": {
"@nucypher/nucypher-core": "^0.7.0",
+ "ferveo-wasm": "^0.1.0",
"axios": "^0.21.1",
"ethers": "^5.4.1",
"joi": "^17.7.0",
diff --git a/test/unit/ferveo-example.test.ts b/test/unit/ferveo-example.test.ts
new file mode 100644
index 000000000..95f229872
--- /dev/null
+++ b/test/unit/ferveo-example.test.ts
@@ -0,0 +1,182 @@
+import {
+ AggregatedTranscript,
+ combineDecryptionSharesPrecomputed,
+ combineDecryptionSharesSimple,
+ DecryptionSharePrecomputed,
+ DecryptionShareSimple,
+ decryptWithSharedSecret,
+ Dkg,
+ encrypt,
+ EthereumAddress,
+ Keypair,
+ Validator,
+ ValidatorMessage,
+} from 'ferveo-wasm';
+
+const zip = (a: Array, b: Array): Array<[A1, A2]> =>
+ a.map((k: A1, i: number) => [k, b[i]]);
+
+const genEthAddr = (i: number) => {
+ const ethAddr =
+ '0x' + '0'.repeat(40 - i.toString(16).length) + i.toString(16);
+ return EthereumAddress.fromString(ethAddr);
+};
+
+function setupTest() {
+ const tau = 1;
+ const sharesNum = 4;
+ const threshold = Math.floor((sharesNum * 2) / 3);
+
+ const validator_keypairs: Keypair[] = [];
+ const validators: Validator[] = [];
+ for (let i = 0; i < sharesNum; i++) {
+ const keypair = Keypair.random();
+ validator_keypairs.push(keypair);
+ const validator = new Validator(genEthAddr(i), keypair.publicKey);
+ validators.push(validator);
+ }
+
+ // Each validator holds their own DKG instance and generates a transcript every
+ // validator, including themselves
+ const messages: ValidatorMessage[] = [];
+ validators.forEach((sender) => {
+ const dkg = new Dkg(tau, sharesNum, threshold, validators, sender);
+ const transcript = dkg.generateTranscript();
+ const message = new ValidatorMessage(sender, transcript);
+ messages.push(message);
+ });
+
+ // Now that every validator holds a dkg instance and a transcript for every other validator,
+ // every validator can aggregate the transcripts
+ const dkg = new Dkg(tau, sharesNum, threshold, validators, validators[0]);
+
+ // Let's say that we've only received `threshold` transcripts
+ const receivedMessages = messages.slice(0, threshold);
+
+ const serverAggregate = dkg.aggregateTranscript(receivedMessages);
+ expect(serverAggregate.verify(sharesNum, receivedMessages)).toBe(true);
+
+ // Client can also aggregate the transcripts and verify them
+ const clientAggregate = new AggregatedTranscript(receivedMessages);
+ expect(clientAggregate.verify(sharesNum, receivedMessages)).toBe(true);
+
+ // In the meantime, the client creates a ciphertext and decryption request
+ const msg = Buffer.from('my-msg');
+ const aad = Buffer.from('my-aad');
+ const ciphertext = encrypt(msg, aad, dkg.finalKey());
+
+ return {
+ tau,
+ sharesNum,
+ threshold,
+ validator_keypairs,
+ validators,
+ dkg,
+ receivedMessages,
+ msg,
+ aad,
+ ciphertext,
+ };
+}
+
+// This test suite replicates tests from ferveo-wasm/tests/node.rs
+describe('ferveo-wasm', () => {
+ it('simple tdec variant', () => {
+ const {
+ tau,
+ sharesNum,
+ threshold,
+ validator_keypairs,
+ validators,
+ dkg,
+ receivedMessages,
+ msg,
+ aad,
+ ciphertext,
+ } = setupTest();
+
+ // Having aggregated the transcripts, the validators can now create decryption shares
+ const decryptionShares: DecryptionShareSimple[] = [];
+ zip(validators, validator_keypairs).forEach(([validator, keypair]) => {
+ expect(validator.publicKey.equals(keypair.publicKey)).toBe(true);
+
+ const dkg = new Dkg(tau, sharesNum, threshold, validators, validator);
+ const aggregate = dkg.aggregateTranscript(receivedMessages);
+ const isValid = aggregate.verify(sharesNum, receivedMessages);
+ expect(isValid).toBe(true);
+
+ const decryptionShare = aggregate.createDecryptionShareSimple(
+ dkg,
+ ciphertext,
+ aad,
+ keypair
+ );
+ decryptionShares.push(decryptionShare);
+ });
+
+ // Now, the decryption share can be used to decrypt the ciphertext
+ // This part is in the client API
+
+ const sharedSecret = combineDecryptionSharesSimple(
+ decryptionShares,
+ dkg.publicParams()
+ );
+
+ // The client should have access to the public parameters of the DKG
+
+ const plaintext = decryptWithSharedSecret(
+ ciphertext,
+ aad,
+ sharedSecret,
+ dkg.publicParams()
+ );
+ expect(Buffer.from(plaintext)).toEqual(msg);
+ });
+
+ it('precomputed tdec variant', () => {
+ const {
+ tau,
+ sharesNum,
+ threshold,
+ validator_keypairs,
+ validators,
+ dkg,
+ receivedMessages,
+ msg,
+ aad,
+ ciphertext,
+ } = setupTest();
+
+ // Having aggregated the transcripts, the validators can now create decryption shares
+ const decryptionShares: DecryptionSharePrecomputed[] = [];
+ zip(validators, validator_keypairs).forEach(([validator, keypair]) => {
+ const dkg = new Dkg(tau, sharesNum, threshold, validators, validator);
+ const aggregate = dkg.aggregateTranscript(receivedMessages);
+ const isValid = aggregate.verify(sharesNum, receivedMessages);
+ expect(isValid).toBe(true);
+
+ const decryptionShare = aggregate.createDecryptionSharePrecomputed(
+ dkg,
+ ciphertext,
+ aad,
+ keypair
+ );
+ decryptionShares.push(decryptionShare);
+ });
+
+ // Now, the decryption share can be used to decrypt the ciphertext
+ // This part is in the client API
+
+ const sharedSecret = combineDecryptionSharesPrecomputed(decryptionShares);
+
+ // The client should have access to the public parameters of the DKG
+
+ const plaintext = decryptWithSharedSecret(
+ ciphertext,
+ aad,
+ sharedSecret,
+ dkg.publicParams()
+ );
+ expect(Buffer.from(plaintext)).toEqual(msg);
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index 98cab979a..c598cf309 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3419,6 +3419,11 @@ fb-watchman@^2.0.0:
dependencies:
bser "2.1.1"
+ferveo-wasm@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/ferveo-wasm/-/ferveo-wasm-0.1.0.tgz#03fa787ed1978f457d4847282d864778a3799f21"
+ integrity sha512-KcPU0QVU/GkXoDeL8mG63Mm6kKyCECmMyF4QGnPqcCSeEXVY+sno67Vk98I/1b372QWsjye/6Rm5J5HBI8icCQ==
+
figures@^3.0.0, figures@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
From 22583506e564d4525e632e35a3b70697b2e43eb9 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 3 May 2023 16:06:06 +0200
Subject: [PATCH 05/98] feat: add coordinator contract
---
abi/Coordinator.json | 550 +++++++++++++++++++++++++++++
src/agents/contracts.ts | 19 +-
src/agents/coordinator.ts | 31 ++
src/agents/subscription-manager.ts | 7 +-
src/config.ts | 4 +
src/types.ts | 1 +
types/ethers-contracts/index.ts | 2 +
7 files changed, 610 insertions(+), 4 deletions(-)
create mode 100644 abi/Coordinator.json
create mode 100644 src/agents/coordinator.ts
diff --git a/abi/Coordinator.json b/abi/Coordinator.json
new file mode 100644
index 000000000..eb2c7f72c
--- /dev/null
+++ b/abi/Coordinator.json
@@ -0,0 +1,550 @@
+{
+ "abi": [
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "_timeout",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint32",
+ "name": "_maxDkgSize",
+ "type": "uint32"
+ },
+ {
+ "internalType": "contract ApplicationInterface",
+ "name": "_application",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "constructor"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "node",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "aggregatedTranscriptDigest",
+ "type": "bytes32"
+ }
+ ],
+ "name": "AggregationPosted",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "initiator",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "enum Coordinator.RitualState",
+ "name": "status",
+ "type": "uint8"
+ }
+ ],
+ "name": "EndRitual",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint32",
+ "name": "oldSize",
+ "type": "uint32"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint32",
+ "name": "newSize",
+ "type": "uint32"
+ }
+ ],
+ "name": "MaxDkgSizeChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "previousOwner",
+ "type": "address"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "OwnershipTransferred",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ }
+ ],
+ "name": "StartAggregationRound",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "initiator",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "address[]",
+ "name": "nodes",
+ "type": "address[]"
+ }
+ ],
+ "name": "StartRitual",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ }
+ ],
+ "name": "StartTranscriptRound",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "internalType": "uint32",
+ "name": "oldTimeout",
+ "type": "uint32"
+ },
+ {
+ "indexed": false,
+ "internalType": "uint32",
+ "name": "newTimeout",
+ "type": "uint32"
+ }
+ ],
+ "name": "TimeoutChanged",
+ "type": "event"
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "node",
+ "type": "address"
+ },
+ {
+ "indexed": false,
+ "internalType": "bytes32",
+ "name": "transcriptDigest",
+ "type": "bytes32"
+ }
+ ],
+ "name": "TranscriptPosted",
+ "type": "event"
+ },
+ {
+ "inputs": [],
+ "name": "PUBLIC_KEY_SIZE",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "applicationInterface",
+ "outputs": [
+ {
+ "internalType": "contract ApplicationInterface",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
+ {
+ "internalType": "address",
+ "name": "node",
+ "type": "address"
+ }
+ ],
+ "name": "getNodeIndex",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ }
+ ],
+ "name": "getParticipants",
+ "outputs": [
+ {
+ "components": [
+ {
+ "internalType": "address",
+ "name": "node",
+ "type": "address"
+ },
+ {
+ "internalType": "bool",
+ "name": "aggregated",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "transcript",
+ "type": "bytes"
+ }
+ ],
+ "internalType": "struct Coordinator.Participant[]",
+ "name": "",
+ "type": "tuple[]"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "ritualId",
+ "type": "uint256"
+ }
+ ],
+ "name": "getRitualState",
+ "outputs": [
+ {
+ "internalType": "enum Coordinator.RitualState",
+ "name": "",
+ "type": "uint8"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address[]",
+ "name": "nodes",
+ "type": "address[]"
+ }
+ ],
+ "name": "initiateRitual",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "maxDkgSize",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "numberOfRituals",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "owner",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nodeIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "aggregatedTranscript",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "publicKey",
+ "type": "bytes"
+ }
+ ],
+ "name": "postAggregation",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "ritualId",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint256",
+ "name": "nodeIndex",
+ "type": "uint256"
+ },
+ {
+ "internalType": "bytes",
+ "name": "transcript",
+ "type": "bytes"
+ }
+ ],
+ "name": "postTranscript",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "renounceOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256"
+ }
+ ],
+ "name": "rituals",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "id",
+ "type": "uint32"
+ },
+ {
+ "internalType": "address",
+ "name": "initiator",
+ "type": "address"
+ },
+ {
+ "internalType": "uint32",
+ "name": "dkgSize",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint32",
+ "name": "initTimestamp",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint32",
+ "name": "totalTranscripts",
+ "type": "uint32"
+ },
+ {
+ "internalType": "uint32",
+ "name": "totalAggregations",
+ "type": "uint32"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "aggregatedTranscriptHash",
+ "type": "bytes32"
+ },
+ {
+ "internalType": "bool",
+ "name": "aggregationMismatch",
+ "type": "bool"
+ },
+ {
+ "internalType": "bytes",
+ "name": "aggregatedTranscript",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes",
+ "name": "publicKey",
+ "type": "bytes"
+ },
+ {
+ "internalType": "bytes32",
+ "name": "publicKeyHash",
+ "type": "bytes32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "newSize",
+ "type": "uint32"
+ }
+ ],
+ "name": "setMaxDkgSize",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint32",
+ "name": "newTimeout",
+ "type": "uint32"
+ }
+ ],
+ "name": "setTimeout",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ },
+ {
+ "inputs": [],
+ "name": "timeout",
+ "outputs": [
+ {
+ "internalType": "uint32",
+ "name": "",
+ "type": "uint32"
+ }
+ ],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "newOwner",
+ "type": "address"
+ }
+ ],
+ "name": "transferOwnership",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function"
+ }
+ ]
+}
diff --git a/src/agents/contracts.ts b/src/agents/contracts.ts
index f967d67d9..79c90bdaf 100644
--- a/src/agents/contracts.ts
+++ b/src/agents/contracts.ts
@@ -2,26 +2,41 @@ import { ChainId, ChecksumAddress } from '../types';
type Contracts = {
readonly SUBSCRIPTION_MANAGER: ChecksumAddress;
+ readonly COORDINATOR: ChecksumAddress;
};
const POLYGON: Contracts = {
SUBSCRIPTION_MANAGER: '0xB0194073421192F6Cf38d72c791Be8729721A0b3',
+ COORDINATOR: '0x0',
};
const MUMBAI: Contracts = {
SUBSCRIPTION_MANAGER: '0xb9015d7b35ce7c81dde38ef7136baa3b1044f313',
+ COORDINATOR: '0x0',
+};
+
+const GOERLI: Contracts = {
+ SUBSCRIPTION_MANAGER: '0x0',
+ COORDINATOR: '0x2cf19429168a0943992D8e7dE534E9b802C687B6',
};
const CONTRACTS: { readonly [key in ChainId]: Contracts } = {
[ChainId.POLYGON]: POLYGON,
[ChainId.MUMBAI]: MUMBAI,
+ [ChainId.GOERLI]: GOERLI,
};
-export const getContracts = (chainId: number): Contracts => {
+export const getContract = (
+ chainId: number,
+ contract: keyof Contracts
+): ChecksumAddress => {
if (!Object.values(ChainId).includes(chainId)) {
throw new Error(`No contracts found for chainId: ${chainId}`);
}
- return CONTRACTS[chainId as ChainId];
+ if (!Object.keys(CONTRACTS[chainId as ChainId]).includes(contract)) {
+ throw new Error(`No contract found for name: ${contract}`);
+ }
+ return CONTRACTS[chainId as ChainId][contract];
};
export const DEFAULT_WAIT_N_CONFIRMATIONS = 1;
diff --git a/src/agents/coordinator.ts b/src/agents/coordinator.ts
new file mode 100644
index 000000000..51c438322
--- /dev/null
+++ b/src/agents/coordinator.ts
@@ -0,0 +1,31 @@
+import { ethers } from 'ethers';
+
+import {
+ Coordinator,
+ Coordinator__factory,
+} from '../../types/ethers-contracts';
+
+import { getContract } from './contracts';
+
+export class CoordinatorAgent {
+ public static async getParticipants(
+ provider: ethers.providers.Provider,
+ ritualId: number
+ ): Promise {
+ const Coordinator = await this.connectReadOnly(provider);
+ return await Coordinator.getParticipants(ritualId);
+ }
+
+ private static async connectReadOnly(provider: ethers.providers.Provider) {
+ return await this.connect(provider);
+ }
+
+ private static async connect(
+ provider: ethers.providers.Provider,
+ signer?: ethers.providers.JsonRpcSigner
+ ): Promise {
+ const network = await provider.getNetwork();
+ const contractAddress = getContract(network.chainId, 'COORDINATOR');
+ return Coordinator__factory.connect(contractAddress, signer ?? provider);
+ }
+}
diff --git a/src/agents/subscription-manager.ts b/src/agents/subscription-manager.ts
index 53bb61685..d05aaed3a 100644
--- a/src/agents/subscription-manager.ts
+++ b/src/agents/subscription-manager.ts
@@ -11,7 +11,7 @@ import {
} from '../../types/ethers-contracts';
import { ChecksumAddress } from '../types';
-import { DEFAULT_WAIT_N_CONFIRMATIONS, getContracts } from './contracts';
+import { DEFAULT_WAIT_N_CONFIRMATIONS, getContract } from './contracts';
export class SubscriptionManagerAgent {
public static async createPolicy(
@@ -76,7 +76,10 @@ export class SubscriptionManagerAgent {
signer?: ethers.providers.JsonRpcSigner
): Promise {
const network = await provider.getNetwork();
- const contractAddress = getContracts(network.chainId).SUBSCRIPTION_MANAGER;
+ const contractAddress = getContract(
+ network.chainId,
+ 'SUBSCRIPTION_MANAGER'
+ );
return SubscriptionManager__factory.connect(
contractAddress,
signer ?? provider
diff --git a/src/config.ts b/src/config.ts
index 32b969429..99bfb02cf 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -11,6 +11,10 @@ const CONFIGS: { readonly [key in ChainId]: Configuration } = {
[ChainId.MUMBAI]: {
porterUri: 'https://porter-tapir.nucypher.community',
},
+ [ChainId.GOERLI]: {
+ // TODO: Confirm this is correct
+ porterUri: 'https://porter-tapir.nucypher.community',
+ },
};
export const defaultConfiguration = (chainId: number): Configuration => {
diff --git a/src/types.ts b/src/types.ts
index 876ff745b..5fedf560e 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -5,4 +5,5 @@ export type Base64EncodedBytes = string;
export enum ChainId {
POLYGON = 137,
MUMBAI = 80001,
+ GOERLI = 5,
}
diff --git a/types/ethers-contracts/index.ts b/types/ethers-contracts/index.ts
index 8bb492b58..a72a65e49 100644
--- a/types/ethers-contracts/index.ts
+++ b/types/ethers-contracts/index.ts
@@ -1,6 +1,8 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
+export type { Coordinator } from "./Coordinator";
export type { SubscriptionManager } from "./SubscriptionManager";
+export { Coordinator__factory } from "./factories/Coordinator__factory";
export { SubscriptionManager__factory } from "./factories/SubscriptionManager__factory";
From 6f3eaf64d6b7c419d7b1159cd0a1a3264266e1ea Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 4 May 2023 11:30:31 +0200
Subject: [PATCH 06/98] feat: add bare-bones impl of dkg client
---
examples/api-example.ts | 9 +-
package.json | 2 +-
src/agents/coordinator.ts | 38 +-
src/agents/subscription-manager.ts | 2 +-
src/dkg.ts | 41 +
src/policies/policy.ts | 6 +-
test/acceptance/alice-grants.test.ts | 16 +-
test/acceptance/delay-enact.test.ts | 14 +-
test/docs/cbd.test.ts | 10 +-
test/integration/conditions.test.ts | 4 +-
test/integration/dkg-client.test.ts | 47 +
test/integration/enrico.test.ts | 14 +-
test/integration/message-kit.test.ts | 4 +-
test/integration/pre.test.ts | 8 +-
test/unit/cohort.test.ts | 8 +-
test/unit/ferveo-example.test.ts | 182 ---
test/unit/strategy.test.ts | 22 +-
test/utils.ts | 207 +++-
yarn.lock | 1546 ++++++++++++++------------
19 files changed, 1218 insertions(+), 962 deletions(-)
create mode 100644 src/dkg.ts
create mode 100644 test/integration/dkg-client.test.ts
delete mode 100644 test/unit/ferveo-example.test.ts
diff --git a/examples/api-example.ts b/examples/api-example.ts
index 6991b2a66..0df37e9ea 100644
--- a/examples/api-example.ts
+++ b/examples/api-example.ts
@@ -1,7 +1,7 @@
import { BlockchainPolicyParameters, Enrico } from '../src';
import { toBytes } from '../src/utils';
-import { fromBytes, mockAlice, mockBob, mockRemoteBob } from '../test/utils';
+import { fromBytes, fakeAlice, fakeBob, fakeRemoteBob } from '../test/utils';
/**
* This is an abridged version of PRE API usage example.
@@ -10,9 +10,9 @@ import { fromBytes, mockAlice, mockBob, mockRemoteBob } from '../test/utils';
async function example() {
// Alice creates a policy and grants access to Bob
- const alice = mockAlice();
+ const alice = fakeAlice();
// `remoteBob` is a just a container for public keys of Bob
- const remoteBob = mockRemoteBob();
+ const remoteBob = fakeRemoteBob();
const policyParams: BlockchainPolicyParameters = {
bob: remoteBob,
label: 'fake-data-label',
@@ -29,7 +29,7 @@ async function example() {
const encryptedMessage = enrico.encryptMessage(toBytes(message));
// Bob retrieves & decrypts encrypted message
- const bob = mockBob();
+ const bob = fakeBob();
const retrievedMessage = await bob.retrieveAndDecrypt(
policy.policyKey,
alice.verifyingKey,
@@ -39,4 +39,3 @@ async function example() {
const bobPlaintext = fromBytes(retrievedMessage[0]);
console.log(bobPlaintext);
}
-
diff --git a/package.json b/package.json
index fc23a9f88..763ab07db 100644
--- a/package.json
+++ b/package.json
@@ -53,7 +53,7 @@
},
"dependencies": {
"@nucypher/nucypher-core": "^0.7.0",
- "ferveo-wasm": "^0.1.0",
+ "ferveo-wasm": "^0.1.1",
"axios": "^0.21.1",
"ethers": "^5.4.1",
"joi": "^17.7.0",
diff --git a/src/agents/coordinator.ts b/src/agents/coordinator.ts
index 51c438322..159492ff9 100644
--- a/src/agents/coordinator.ts
+++ b/src/agents/coordinator.ts
@@ -7,13 +7,45 @@ import {
import { getContract } from './contracts';
-export class CoordinatorAgent {
+export interface DkgRitual {
+ id: number;
+ initiator: string;
+ dkgSize: number;
+ initTimestamp: number;
+ totalTranscripts: number;
+ totalAggregations: number;
+ aggregatedTranscriptHash: string;
+ aggregationMismatch: boolean;
+ aggregatedTranscript: string;
+ publicKey: string;
+ publicKeyHash: string;
+}
+
+export interface DkgParticipant {
+ node: string;
+ aggregated: boolean;
+ transcript: string;
+ publicKey: string;
+}
+
+export class DkgCoordinatorAgent {
public static async getParticipants(
provider: ethers.providers.Provider,
ritualId: number
- ): Promise {
+ ): Promise {
+ const Coordinator = await this.connectReadOnly(provider);
+ // TODO: Remove `as unknown` cast after regenerating the contract types: https://github.com/nucypher/nucypher-contracts/pull/77
+ return (await Coordinator.getParticipants(
+ ritualId
+ )) as unknown as DkgParticipant[];
+ }
+
+ public static async getRitual(
+ provider: ethers.providers.Provider,
+ ritualId: number
+ ): Promise {
const Coordinator = await this.connectReadOnly(provider);
- return await Coordinator.getParticipants(ritualId);
+ return await Coordinator.rituals(ritualId);
}
private static async connectReadOnly(provider: ethers.providers.Provider) {
diff --git a/src/agents/subscription-manager.ts b/src/agents/subscription-manager.ts
index d05aaed3a..ac8a5a3c5 100644
--- a/src/agents/subscription-manager.ts
+++ b/src/agents/subscription-manager.ts
@@ -13,7 +13,7 @@ import { ChecksumAddress } from '../types';
import { DEFAULT_WAIT_N_CONFIRMATIONS, getContract } from './contracts';
-export class SubscriptionManagerAgent {
+export class PreSubscriptionManagerAgent {
public static async createPolicy(
web3Provider: ethers.providers.Web3Provider,
valueInWei: BigNumber,
diff --git a/src/dkg.ts b/src/dkg.ts
new file mode 100644
index 000000000..1230babd5
--- /dev/null
+++ b/src/dkg.ts
@@ -0,0 +1,41 @@
+import { ethers } from 'ethers';
+import {
+ AggregatedTranscript,
+ EthereumAddress,
+ PublicKey as FerveoPublicKey,
+ Transcript,
+ Validator,
+ ValidatorMessage,
+} from 'ferveo-wasm';
+
+import { DkgCoordinatorAgent } from './agents/coordinator';
+import { fromHexString } from './utils';
+
+export class DkgClient {
+ constructor(
+ private readonly provider: ethers.providers.Web3Provider,
+ public readonly ritualId: number
+ ) {}
+
+ public async verifyRitual(): Promise {
+ const ritual = await DkgCoordinatorAgent.getRitual(
+ this.provider,
+ this.ritualId
+ );
+ const participants = await DkgCoordinatorAgent.getParticipants(
+ this.provider,
+ this.ritualId
+ );
+
+ const validatorMessages = participants.map((p) => {
+ const validatorAddress = EthereumAddress.fromString(p.node);
+ const publicKey = FerveoPublicKey.fromBytes(fromHexString(p.publicKey));
+ const validator = new Validator(validatorAddress, publicKey);
+ const transcript = Transcript.fromBytes(fromHexString(p.transcript));
+ return new ValidatorMessage(validator, transcript);
+ });
+ const aggregate = new AggregatedTranscript(validatorMessages);
+
+ return aggregate.verify(ritual.dkgSize, validatorMessages);
+ }
+}
diff --git a/src/policies/policy.ts b/src/policies/policy.ts
index dbb23eccb..0e01a6926 100644
--- a/src/policies/policy.ts
+++ b/src/policies/policy.ts
@@ -7,7 +7,7 @@ import {
VerifiedKeyFrag,
} from '@nucypher/nucypher-core';
-import { SubscriptionManagerAgent } from '../agents/subscription-manager';
+import { PreSubscriptionManagerAgent } from '../agents/subscription-manager';
import { Alice } from '../characters/alice';
import { RemoteBob } from '../characters/bob';
import { Ursula } from '../characters/porter';
@@ -64,13 +64,13 @@ export class PreEnactedPolicy implements IPreEnactedPolicy {
const startTimestamp = toEpoch(this.startTimestamp);
const endTimestamp = toEpoch(this.endTimestamp);
const ownerAddress = await publisher.web3Provider.getSigner().getAddress();
- const value = await SubscriptionManagerAgent.getPolicyCost(
+ const value = await PreSubscriptionManagerAgent.getPolicyCost(
publisher.web3Provider,
this.size,
startTimestamp,
endTimestamp
);
- const tx = await SubscriptionManagerAgent.createPolicy(
+ const tx = await PreSubscriptionManagerAgent.createPolicy(
publisher.web3Provider,
value,
this.id.toBytes(),
diff --git a/test/acceptance/alice-grants.test.ts b/test/acceptance/alice-grants.test.ts
index f4414e2bb..c234c1078 100644
--- a/test/acceptance/alice-grants.test.ts
+++ b/test/acceptance/alice-grants.test.ts
@@ -11,16 +11,16 @@ import { ChecksumAddress } from '../../src/types';
import { toBytes } from '../../src/utils';
import {
bytesEqual,
+ fakeAlice,
+ fakeBob,
+ fakeRemoteBob,
+ fakeUrsulas,
fromBytes,
- makeTestUrsulas,
- mockAlice,
- mockBob,
mockEncryptTreasureMap,
mockGenerateKFrags,
mockGetUrsulas,
mockMakeTreasureMap,
mockPublishToBlockchain,
- mockRemoteBob,
mockRetrieveCFragsRequest,
reencryptKFrags,
} from '../utils';
@@ -31,7 +31,7 @@ describe('story: alice shares message with bob through policy', () => {
const shares = 3;
const startDate = new Date();
const endDate = new Date(Date.now() + 60 * 1000);
- const mockedUrsulas = makeTestUrsulas().slice(0, shares);
+ const mockedUrsulas = fakeUrsulas().slice(0, shares);
// Intermediate variables used for mocking
let encryptedTreasureMap: EncryptedTreasureMap;
@@ -52,8 +52,8 @@ describe('story: alice shares message with bob through policy', () => {
const makeTreasureMapSpy = mockMakeTreasureMap();
const encryptTreasureMapSpy = mockEncryptTreasureMap();
- const alice = mockAlice();
- const bob = mockRemoteBob();
+ const alice = fakeAlice();
+ const bob = fakeRemoteBob();
const policyParams = {
bob,
label,
@@ -92,7 +92,7 @@ describe('story: alice shares message with bob through policy', () => {
});
it('bob retrieves and decrypts the message', async () => {
- const bob = mockBob();
+ const bob = fakeBob();
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const retrieveCFragsSpy = mockRetrieveCFragsRequest(
ursulaAddresses,
diff --git a/test/acceptance/delay-enact.test.ts b/test/acceptance/delay-enact.test.ts
index 151719f6f..ddd99d1b7 100644
--- a/test/acceptance/delay-enact.test.ts
+++ b/test/acceptance/delay-enact.test.ts
@@ -1,11 +1,11 @@
import {
- makeTestUrsulas,
- mockAlice,
+ fakeAlice,
+ fakeRemoteBob,
+ fakeUrsulas,
mockEncryptTreasureMap,
mockGenerateKFrags,
mockGetUrsulas,
mockPublishToBlockchain,
- mockRemoteBob,
} from '../utils';
describe('story: alice1 creates a policy but alice2 enacts it', () => {
@@ -13,7 +13,7 @@ describe('story: alice1 creates a policy but alice2 enacts it', () => {
const shares = 3;
const startDate = new Date();
const endDate = new Date(Date.now() + 60 * 1000); // 60s later
- const mockedUrsulas = makeTestUrsulas().slice(0, shares);
+ const mockedUrsulas = fakeUrsulas().slice(0, shares);
const label = 'fake-data-label';
it('alice generates a new policy', async () => {
@@ -22,9 +22,9 @@ describe('story: alice1 creates a policy but alice2 enacts it', () => {
const publishToBlockchainSpy = mockPublishToBlockchain();
const encryptTreasureMapSpy = mockEncryptTreasureMap();
- const alice1 = mockAlice('fake-secret-key-32-bytes-alice-1');
- const alice2 = mockAlice('fake-secret-key-32-bytes-alice-2');
- const bob = mockRemoteBob();
+ const alice1 = fakeAlice('fake-secret-key-32-bytes-alice-1');
+ const alice2 = fakeAlice('fake-secret-key-32-bytes-alice-2');
+ const bob = fakeRemoteBob();
const policyParams = {
bob,
label,
diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts
index 956448355..630091eb1 100644
--- a/test/docs/cbd.test.ts
+++ b/test/docs/cbd.test.ts
@@ -11,7 +11,8 @@ import {
import { Ursula } from '../../src/characters/porter';
import { toBytes } from '../../src/utils';
import {
- makeTestUrsulas,
+ fakeUrsulas,
+ fakeWeb3Provider,
mockDetectEthereumProvider,
mockEncryptTreasureMap,
mockGenerateKFrags,
@@ -19,7 +20,6 @@ import {
mockMakeTreasureMap,
mockPublishToBlockchain,
mockRetrieveCFragsRequest,
- mockWeb3Provider,
} from '../utils';
describe('Get Started (CBD PoC)', () => {
@@ -42,7 +42,7 @@ describe('Get Started (CBD PoC)', () => {
it('can run the get started example', async () => {
const detectEthereumProvider = mockDetectEthereumProvider();
- const mockedUrsulas = makeTestUrsulas();
+ const mockedUrsulas = fakeUrsulas();
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -52,7 +52,7 @@ describe('Get Started (CBD PoC)', () => {
jest
.spyOn(providers, 'Web3Provider')
.mockImplementation(() =>
- mockWeb3Provider(SecretKey.random().toBEBytes())
+ fakeWeb3Provider(SecretKey.random().toBEBytes())
);
//
@@ -126,7 +126,7 @@ describe('Get Started (CBD PoC)', () => {
// End of the code example
//
- const expectedAddresses = makeTestUrsulas().map((u) => u.checksumAddress);
+ const expectedAddresses = fakeUrsulas().map((u) => u.checksumAddress);
const condObj = conditions.conditions[0].toObj();
expect(newCohort.ursulaAddresses).toEqual(expectedAddresses);
expect(condObj.parameters).toEqual([5954]);
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index 373a2d54e..870f1c1dc 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -6,7 +6,7 @@ import {
ConditionSet,
Operator,
} from '../../src';
-import { mockWeb3Provider } from '../utils';
+import { fakeWeb3Provider } from '../utils';
describe('operator', () => {
it('should validate Operator', async () => {
@@ -239,7 +239,7 @@ describe('produce context parameters from conditions', () => {
describe('condition context', () => {
it('should serialize to JSON with context params', async () => {
- const web3Provider = mockWeb3Provider(SecretKey.random().toBEBytes());
+ const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
const rpcCondition = new Conditions.RpcCondition({
chain: 5,
diff --git a/test/integration/dkg-client.test.ts b/test/integration/dkg-client.test.ts
new file mode 100644
index 000000000..13a76aa82
--- /dev/null
+++ b/test/integration/dkg-client.test.ts
@@ -0,0 +1,47 @@
+import { SecretKey } from '@nucypher/nucypher-core';
+
+import { DkgCoordinatorAgent } from '../../src/agents/coordinator';
+import { DkgClient } from '../../src/dkg';
+import { fakeDkgParticipants, fakeDkgRitual, fakeWeb3Provider } from '../utils';
+
+const ritualId = 0;
+
+jest.mock('../../src/agents/coordinator', () => ({
+ DkgCoordinatorAgent: {
+ getRitual: () => Promise.resolve(fakeDkgRitual(ritualId)),
+ getParticipants: () => Promise.resolve(fakeDkgParticipants()),
+ },
+}));
+
+describe('DkgCoordinatorAgent', () => {
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ it('fetches transcripts from the coordinator', async () => {
+ const provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
+ const ritual = await DkgCoordinatorAgent.getRitual(provider, ritualId);
+
+ expect(ritual.id).toEqual(ritualId);
+ });
+
+ it('fetches participants from the coordinator', async () => {
+ const provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
+ const participants = await DkgCoordinatorAgent.getParticipants(
+ provider,
+ ritualId
+ );
+
+ expect(participants.length).toBeGreaterThan(0);
+ });
+});
+
+describe('DkgClient', () => {
+ it('verifies the dkg ritual', async () => {
+ const provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
+
+ const dkgClient = new DkgClient(provider, ritualId);
+ const isValid = await dkgClient.verifyRitual();
+ expect(isValid).toBe(true);
+ });
+});
diff --git a/test/integration/enrico.test.ts b/test/integration/enrico.test.ts
index fb57894c4..c45c2e452 100644
--- a/test/integration/enrico.test.ts
+++ b/test/integration/enrico.test.ts
@@ -4,9 +4,9 @@ import { RetrievalResult } from '../../src/kits/retrieval';
import { toBytes } from '../../src/utils';
import {
bytesEqual,
+ fakeAlice,
+ fakeBob,
fromBytes,
- mockAlice,
- mockBob,
reencryptKFrags,
} from '../utils';
@@ -14,7 +14,7 @@ describe('enrico', () => {
it('alice decrypts message encrypted by enrico', async () => {
const label = 'fake-label';
const message = 'fake-message';
- const alice = mockAlice();
+ const alice = fakeAlice();
const policyKey = alice.getPolicyEncryptingKeyFromLabel(label);
const enrico = new Enrico(policyKey);
@@ -28,8 +28,8 @@ describe('enrico', () => {
it('bob decrypts reencrypted message', async () => {
const label = 'fake-label';
- const alice = mockAlice();
- const bob = mockBob();
+ const alice = fakeAlice();
+ const bob = fakeBob();
const policyEncryptingKey = alice.getPolicyEncryptingKeyFromLabel(label);
const enrico = new Enrico(policyEncryptingKey);
@@ -89,7 +89,7 @@ describe('enrico', () => {
it('enrico generates a message kit with conditions', async () => {
const label = 'fake-label';
const message = 'fake-message';
- const alice = mockAlice();
+ const alice = fakeAlice();
const policyKey = alice.getPolicyEncryptingKeyFromLabel(label);
@@ -112,7 +112,7 @@ describe('enrico', () => {
it('can overwrite conditions at encryption time', async () => {
const label = 'fake-label';
const message = 'fake-message';
- const alice = mockAlice();
+ const alice = fakeAlice();
const policyKey = alice.getPolicyEncryptingKeyFromLabel(label);
diff --git a/test/integration/message-kit.test.ts b/test/integration/message-kit.test.ts
index c4070a0c0..16d27640b 100644
--- a/test/integration/message-kit.test.ts
+++ b/test/integration/message-kit.test.ts
@@ -1,10 +1,10 @@
import { MessageKit } from '../../src';
import { toBytes } from '../../src/utils';
-import { mockBob } from '../utils';
+import { fakeBob } from '../utils';
describe('message kit', () => {
it('bob decrypts', () => {
- const bob = mockBob();
+ const bob = fakeBob();
const plaintext = toBytes('fake-message');
const messageKit = new MessageKit(bob.decryptingKey, plaintext, null);
const decrypted = bob['keyring'].decrypt(messageKit);
diff --git a/test/integration/pre.test.ts b/test/integration/pre.test.ts
index b5bf3c311..ef3565a42 100644
--- a/test/integration/pre.test.ts
+++ b/test/integration/pre.test.ts
@@ -10,16 +10,16 @@ import {
} from '../../src';
import { RetrievalResult } from '../../src/kits/retrieval';
import { toBytes, zip } from '../../src/utils';
-import { makeTestUrsulas, mockAlice, mockBob, reencryptKFrags } from '../utils';
+import { fakeAlice, fakeBob, fakeUrsulas, reencryptKFrags } from '../utils';
describe('proxy reencryption', () => {
const plaintext = toBytes('plaintext-message');
const threshold = 2;
const shares = 3;
- const ursulas = makeTestUrsulas().slice(0, shares);
+ const ursulas = fakeUrsulas().slice(0, shares);
const label = 'fake-data-label';
- const alice = mockAlice();
- const bob = mockBob();
+ const alice = fakeAlice();
+ const bob = fakeBob();
it('verifies capsule frags', async () => {
const { capsule } = new MessageKit(bob.decryptingKey, plaintext, null);
diff --git a/test/unit/cohort.test.ts b/test/unit/cohort.test.ts
index 7cfd66eea..80ca256eb 100644
--- a/test/unit/cohort.test.ts
+++ b/test/unit/cohort.test.ts
@@ -1,9 +1,9 @@
import { Cohort } from '../../src';
-import { makeTestUrsulas, mockGetUrsulas } from '../utils';
+import { fakeUrsulas, mockGetUrsulas } from '../utils';
describe('Cohort', () => {
it('can create Cohort from configuration', async () => {
- const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const config = {
@@ -23,7 +23,7 @@ describe('Cohort', () => {
});
it('can export to JSON', async () => {
- const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const config = {
threshold: 2,
@@ -39,7 +39,7 @@ describe('Cohort', () => {
});
it('can import from JSON', async () => {
- const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const configJSON =
diff --git a/test/unit/ferveo-example.test.ts b/test/unit/ferveo-example.test.ts
deleted file mode 100644
index 95f229872..000000000
--- a/test/unit/ferveo-example.test.ts
+++ /dev/null
@@ -1,182 +0,0 @@
-import {
- AggregatedTranscript,
- combineDecryptionSharesPrecomputed,
- combineDecryptionSharesSimple,
- DecryptionSharePrecomputed,
- DecryptionShareSimple,
- decryptWithSharedSecret,
- Dkg,
- encrypt,
- EthereumAddress,
- Keypair,
- Validator,
- ValidatorMessage,
-} from 'ferveo-wasm';
-
-const zip = (a: Array, b: Array): Array<[A1, A2]> =>
- a.map((k: A1, i: number) => [k, b[i]]);
-
-const genEthAddr = (i: number) => {
- const ethAddr =
- '0x' + '0'.repeat(40 - i.toString(16).length) + i.toString(16);
- return EthereumAddress.fromString(ethAddr);
-};
-
-function setupTest() {
- const tau = 1;
- const sharesNum = 4;
- const threshold = Math.floor((sharesNum * 2) / 3);
-
- const validator_keypairs: Keypair[] = [];
- const validators: Validator[] = [];
- for (let i = 0; i < sharesNum; i++) {
- const keypair = Keypair.random();
- validator_keypairs.push(keypair);
- const validator = new Validator(genEthAddr(i), keypair.publicKey);
- validators.push(validator);
- }
-
- // Each validator holds their own DKG instance and generates a transcript every
- // validator, including themselves
- const messages: ValidatorMessage[] = [];
- validators.forEach((sender) => {
- const dkg = new Dkg(tau, sharesNum, threshold, validators, sender);
- const transcript = dkg.generateTranscript();
- const message = new ValidatorMessage(sender, transcript);
- messages.push(message);
- });
-
- // Now that every validator holds a dkg instance and a transcript for every other validator,
- // every validator can aggregate the transcripts
- const dkg = new Dkg(tau, sharesNum, threshold, validators, validators[0]);
-
- // Let's say that we've only received `threshold` transcripts
- const receivedMessages = messages.slice(0, threshold);
-
- const serverAggregate = dkg.aggregateTranscript(receivedMessages);
- expect(serverAggregate.verify(sharesNum, receivedMessages)).toBe(true);
-
- // Client can also aggregate the transcripts and verify them
- const clientAggregate = new AggregatedTranscript(receivedMessages);
- expect(clientAggregate.verify(sharesNum, receivedMessages)).toBe(true);
-
- // In the meantime, the client creates a ciphertext and decryption request
- const msg = Buffer.from('my-msg');
- const aad = Buffer.from('my-aad');
- const ciphertext = encrypt(msg, aad, dkg.finalKey());
-
- return {
- tau,
- sharesNum,
- threshold,
- validator_keypairs,
- validators,
- dkg,
- receivedMessages,
- msg,
- aad,
- ciphertext,
- };
-}
-
-// This test suite replicates tests from ferveo-wasm/tests/node.rs
-describe('ferveo-wasm', () => {
- it('simple tdec variant', () => {
- const {
- tau,
- sharesNum,
- threshold,
- validator_keypairs,
- validators,
- dkg,
- receivedMessages,
- msg,
- aad,
- ciphertext,
- } = setupTest();
-
- // Having aggregated the transcripts, the validators can now create decryption shares
- const decryptionShares: DecryptionShareSimple[] = [];
- zip(validators, validator_keypairs).forEach(([validator, keypair]) => {
- expect(validator.publicKey.equals(keypair.publicKey)).toBe(true);
-
- const dkg = new Dkg(tau, sharesNum, threshold, validators, validator);
- const aggregate = dkg.aggregateTranscript(receivedMessages);
- const isValid = aggregate.verify(sharesNum, receivedMessages);
- expect(isValid).toBe(true);
-
- const decryptionShare = aggregate.createDecryptionShareSimple(
- dkg,
- ciphertext,
- aad,
- keypair
- );
- decryptionShares.push(decryptionShare);
- });
-
- // Now, the decryption share can be used to decrypt the ciphertext
- // This part is in the client API
-
- const sharedSecret = combineDecryptionSharesSimple(
- decryptionShares,
- dkg.publicParams()
- );
-
- // The client should have access to the public parameters of the DKG
-
- const plaintext = decryptWithSharedSecret(
- ciphertext,
- aad,
- sharedSecret,
- dkg.publicParams()
- );
- expect(Buffer.from(plaintext)).toEqual(msg);
- });
-
- it('precomputed tdec variant', () => {
- const {
- tau,
- sharesNum,
- threshold,
- validator_keypairs,
- validators,
- dkg,
- receivedMessages,
- msg,
- aad,
- ciphertext,
- } = setupTest();
-
- // Having aggregated the transcripts, the validators can now create decryption shares
- const decryptionShares: DecryptionSharePrecomputed[] = [];
- zip(validators, validator_keypairs).forEach(([validator, keypair]) => {
- const dkg = new Dkg(tau, sharesNum, threshold, validators, validator);
- const aggregate = dkg.aggregateTranscript(receivedMessages);
- const isValid = aggregate.verify(sharesNum, receivedMessages);
- expect(isValid).toBe(true);
-
- const decryptionShare = aggregate.createDecryptionSharePrecomputed(
- dkg,
- ciphertext,
- aad,
- keypair
- );
- decryptionShares.push(decryptionShare);
- });
-
- // Now, the decryption share can be used to decrypt the ciphertext
- // This part is in the client API
-
- const sharedSecret = combineDecryptionSharesPrecomputed(decryptionShares);
-
- // The client should have access to the public parameters of the DKG
-
- const plaintext = decryptWithSharedSecret(
- ciphertext,
- aad,
- sharedSecret,
- dkg.publicParams()
- );
- expect(Buffer.from(plaintext)).toEqual(msg);
- });
-});
diff --git a/test/unit/strategy.test.ts b/test/unit/strategy.test.ts
index 38ada25b3..5c49eeaa3 100644
--- a/test/unit/strategy.test.ts
+++ b/test/unit/strategy.test.ts
@@ -15,14 +15,14 @@ import {
import { Ursula } from '../../src/characters/porter';
import { fromBase64, toBytes } from '../../src/utils';
import {
- makeTestUrsulas,
+ fakeUrsulas,
+ fakeWeb3Provider,
mockEncryptTreasureMap,
mockGenerateKFrags,
mockGetUrsulas,
mockMakeTreasureMap,
mockPublishToBlockchain,
mockRetrieveCFragsRequest,
- mockWeb3Provider,
} from '../utils';
import {
@@ -42,7 +42,7 @@ describe('Strategy', () => {
};
const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
- const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
+ const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
Date.now = jest.fn(() => 1487076708000);
afterEach(() => {
@@ -50,7 +50,7 @@ describe('Strategy', () => {
});
it('can create Strategy from configuration', async () => {
- const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const testCohort = await Cohort.create(cohortConfig);
@@ -69,7 +69,7 @@ describe('Strategy', () => {
});
it('can export to JSON', async () => {
- const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const testCohort = await Cohort.create(cohortConfig);
const testStrategy = Strategy.create(
@@ -97,7 +97,7 @@ describe('Strategy', () => {
});
it('can deploy and return DeployedStrategy', async () => {
- const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -131,8 +131,8 @@ describe('Deployed Strategy', () => {
});
it('can export to JSON', async () => {
- const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
- const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -168,9 +168,9 @@ describe('Deployed Strategy', () => {
});
it('can encrypt and decrypt', async () => {
- const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
- const bobProvider = mockWeb3Provider(bobSecretKey.toBEBytes());
- const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
+ const bobProvider = fakeWeb3Provider(bobSecretKey.toBEBytes());
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
diff --git a/test/utils.ts b/test/utils.ts
index f4a0bac71..b735af163 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -14,8 +14,25 @@ import {
} from '@nucypher/nucypher-core';
import axios from 'axios';
import { ethers, providers, Wallet } from 'ethers';
+import { keccak256 } from 'ethers/lib/utils';
+import {
+ AggregatedTranscript,
+ combineDecryptionSharesPrecomputed,
+ combineDecryptionSharesSimple,
+ DecryptionSharePrecomputed,
+ DecryptionShareSimple,
+ decryptWithSharedSecret,
+ Dkg,
+ encrypt,
+ EthereumAddress,
+ Keypair,
+ Transcript,
+ Validator,
+ ValidatorMessage,
+} from 'ferveo-wasm';
import { Alice, Bob, Configuration, RemoteBob } from '../src';
+import { DkgParticipant, DkgRitual } from '../src/agents/coordinator';
import {
GetUrsulasResponse,
Porter,
@@ -37,25 +54,25 @@ const mockConfig: Configuration = {
porterUri: 'https://_this_should_crash.com/',
};
-export const mockBob = (): Bob => {
+export const fakeBob = (): Bob => {
const secretKey = SecretKey.fromBEBytes(
toBytes('fake-secret-key-32-bytes-bob-xxx')
);
return Bob.fromSecretKey(mockConfig, secretKey);
};
-export const mockRemoteBob = (): RemoteBob => {
- const { decryptingKey, verifyingKey } = mockBob();
+export const fakeRemoteBob = (): RemoteBob => {
+ const { decryptingKey, verifyingKey } = fakeBob();
return RemoteBob.fromKeys(decryptingKey, verifyingKey);
};
-export const mockAlice = (aliceKey = 'fake-secret-key-32-bytes-alice-x') => {
+export const fakeAlice = (aliceKey = 'fake-secret-key-32-bytes-alice-x') => {
const secretKey = SecretKey.fromBEBytes(toBytes(aliceKey));
- const provider = mockWeb3Provider(secretKey.toBEBytes());
+ const provider = fakeWeb3Provider(secretKey.toBEBytes());
return Alice.fromSecretKey(mockConfig, secretKey, provider);
};
-export const mockWeb3Provider = (
+export const fakeWeb3Provider = (
secretKeyBytes: Uint8Array,
blockNumber?: number,
blockTimestamp?: number
@@ -66,7 +83,6 @@ export const mockWeb3Provider = (
getBlock: () => Promise.resolve(block as Block),
_isProvider: true,
getNetwork: () => Promise.resolve({ name: 'mockNetwork', chainId: -1 }),
- request: () => '',
};
const fakeSignerWithProvider = {
...new Wallet(secretKeyBytes),
@@ -81,7 +97,7 @@ export const mockWeb3Provider = (
} as unknown as ethers.providers.Web3Provider;
};
-export const makeTestUrsulas = (): readonly Ursula[] => {
+export const fakeUrsulas = (): readonly Ursula[] => {
return [
{
encryptingKey: SecretKey.random().publicKey(),
@@ -118,7 +134,7 @@ export const makeTestUrsulas = (): readonly Ursula[] => {
};
export const mockGetUrsulas = (ursulas: readonly Ursula[]) => {
- const mockPorterUrsulas = (
+ const fakePorterUrsulas = (
mockUrsulas: readonly Ursula[]
): GetUrsulasResponse => {
return {
@@ -134,7 +150,7 @@ export const mockGetUrsulas = (ursulas: readonly Ursula[]) => {
};
return jest.spyOn(axios, 'get').mockImplementation(async () => {
- return Promise.resolve({ data: mockPorterUrsulas(ursulas) });
+ return Promise.resolve({ data: fakePorterUrsulas(ursulas) });
});
};
export const mockPublishToBlockchain = () => {
@@ -144,7 +160,7 @@ export const mockPublishToBlockchain = () => {
.mockImplementation(async () => Promise.resolve(txHash));
};
-export const mockCFragResponse = (
+const fakeCFragResponse = (
ursulas: readonly ChecksumAddress[],
verifiedKFrags: readonly VerifiedKeyFrag[],
capsule: Capsule
@@ -161,20 +177,13 @@ export const mockRetrieveCFragsRequest = (
verifiedKFrags: readonly VerifiedKeyFrag[],
capsule: Capsule
) => {
- const results = mockCFragResponse(ursulas, verifiedKFrags, capsule);
+ const results = fakeCFragResponse(ursulas, verifiedKFrags, capsule);
return jest
.spyOn(Porter.prototype, 'retrieveCFrags')
.mockImplementation(() => {
return Promise.resolve(results);
});
};
-
-export const mockRetrieveCFragsRequestThrows = () => {
- return jest
- .spyOn(Porter.prototype, 'retrieveCFrags')
- .mockRejectedValue(new Error('fake-reencryption-request-failed-error'));
-};
-
export const mockGenerateKFrags = (withValue?: {
delegatingKey: PublicKey;
verifiedKFrags: VerifiedKeyFrag[];
@@ -219,3 +228,163 @@ export const mockDetectEthereumProvider = () => {
return {} as unknown as providers.ExternalProvider;
});
};
+
+const fakeDkgRitualE2e = (variant: 'precomputed' | 'simple') => {
+ if (variant !== 'precomputed' && variant !== 'simple') {
+ throw new Error(`Invalid variant: ${variant}`);
+ }
+
+ const genEthAddr = (i: number) => {
+ const ethAddr =
+ '0x' + '0'.repeat(40 - i.toString(16).length) + i.toString(16);
+ return EthereumAddress.fromString(ethAddr);
+ };
+
+ const tau = 1;
+ const sharesNum = 4;
+ const threshold = Math.floor((sharesNum * 2) / 3);
+
+ const validator_keypairs: Keypair[] = [];
+ const validators: Validator[] = [];
+ for (let i = 0; i < sharesNum; i++) {
+ const keypair = Keypair.random();
+ validator_keypairs.push(keypair);
+ const validator = new Validator(genEthAddr(i), keypair.publicKey);
+ validators.push(validator);
+ }
+
+ // Each validator holds their own DKG instance and generates a transcript every
+ // validator, including themselves
+ const messages: ValidatorMessage[] = [];
+ const transcripts: Transcript[] = [];
+ validators.forEach((sender) => {
+ const dkg = new Dkg(tau, sharesNum, threshold, validators, sender);
+ const transcript = dkg.generateTranscript();
+ transcripts.push(transcript);
+ const message = new ValidatorMessage(sender, transcript);
+ messages.push(message);
+ });
+
+ // Now that every validator holds a dkg instance and a transcript for every other validator,
+ // every validator can aggregate the transcripts
+ const dkg = new Dkg(tau, sharesNum, threshold, validators, validators[0]);
+
+ // Let's say that we've only received `threshold` transcripts
+ const receivedMessages = messages.slice(0, threshold);
+
+ const serverAggregate = dkg.aggregateTranscript(receivedMessages);
+ expect(serverAggregate.verify(sharesNum, receivedMessages)).toBe(true);
+
+ // Client can also aggregate the transcripts and verify them
+ const clientAggregate = new AggregatedTranscript(receivedMessages);
+ expect(clientAggregate.verify(sharesNum, receivedMessages)).toBe(true);
+
+ // In the meantime, the client creates a ciphertext and decryption request
+ const msg = Buffer.from('my-msg');
+ const aad = Buffer.from('my-aad');
+ const ciphertext = encrypt(msg, aad, dkg.finalKey());
+
+ // Having aggregated the transcripts, the validators can now create decryption shares
+ const decryptionShares: (
+ | DecryptionSharePrecomputed
+ | DecryptionShareSimple
+ )[] = [];
+ zip(validators, validator_keypairs).forEach(([validator, keypair]) => {
+ const dkg = new Dkg(tau, sharesNum, threshold, validators, validator);
+ const aggregate = dkg.aggregateTranscript(receivedMessages);
+ const isValid = aggregate.verify(sharesNum, receivedMessages);
+ if (!isValid) {
+ throw new Error('Transcript is invalid');
+ }
+
+ let decryptionShare;
+
+ if (variant === 'precomputed') {
+ decryptionShare = aggregate.createDecryptionSharePrecomputed(
+ dkg,
+ ciphertext,
+ aad,
+ keypair
+ );
+ } else {
+ decryptionShare = aggregate.createDecryptionShareSimple(
+ dkg,
+ ciphertext,
+ aad,
+ keypair
+ );
+ }
+ decryptionShares.push(decryptionShare);
+ });
+
+ // Now, the decryption share can be used to decrypt the ciphertext
+ // This part is in the client API
+
+ let sharedSecret;
+ if (variant === 'precomputed') {
+ sharedSecret = combineDecryptionSharesPrecomputed(decryptionShares);
+ } else {
+ sharedSecret = combineDecryptionSharesSimple(
+ decryptionShares,
+ dkg.publicParams()
+ );
+ }
+
+ // The client should have access to the public parameters of the DKG
+ const plaintext = decryptWithSharedSecret(
+ ciphertext,
+ aad,
+ sharedSecret,
+ dkg.publicParams()
+ );
+ if (!bytesEqual(plaintext, msg)) {
+ throw new Error('Decryption failed');
+ }
+
+ return {
+ tau,
+ sharesNum,
+ threshold,
+ validator_keypairs,
+ validators,
+ transcripts,
+ dkg,
+ receivedMessages,
+ msg,
+ aad,
+ ciphertext,
+ serverAggregate,
+ };
+};
+
+export const fakeDkgRitual = (ritualId: number): DkgRitual => {
+ const ritual = fakeDkgRitualE2e('precomputed');
+ return {
+ id: ritualId,
+ initiator: ritual.validators[0].address.toString(),
+ dkgSize: ritual.sharesNum,
+ initTimestamp: 0,
+ totalTranscripts: ritual.receivedMessages.length,
+ totalAggregations: ritual.sharesNum, // Assuming the ritual is finished
+ aggregatedTranscriptHash: keccak256(ritual.serverAggregate.toBytes()),
+ aggregationMismatch: false, // Assuming the ritual is correct
+ aggregatedTranscript: toHexString(ritual.serverAggregate.toBytes()),
+ publicKey: toHexString(ritual.dkg.finalKey().toBytes()),
+ publicKeyHash: keccak256(ritual.dkg.finalKey().toBytes()),
+ };
+};
+
+export const fakeDkgParticipants = (): DkgParticipant[] => {
+ const ritual = fakeDkgRitualE2e('precomputed');
+ return zip(
+ zip(ritual.validators, ritual.transcripts),
+ ritual.validator_keypairs
+ ).map(([[v, t], k]) => {
+ return {
+ node: v.address.toString(),
+ aggregated: true, // Assuming all validators already contributed to the aggregate
+ transcript: toHexString(t.toBytes()),
+ publicKey: toHexString(k.publicKey.toBytes()),
+ };
+ });
+};
diff --git a/yarn.lock b/yarn.lock
index c598cf309..4df504fb2 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,12 +2,12 @@
# yarn lockfile v1
-"@ampproject/remapping@^2.1.0":
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
- integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==
+"@ampproject/remapping@^2.2.0":
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630"
+ integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==
dependencies:
- "@jridgewell/gen-mapping" "^0.1.0"
+ "@jridgewell/gen-mapping" "^0.3.0"
"@jridgewell/trace-mapping" "^0.3.9"
"@babel/code-frame@7.12.11":
@@ -17,46 +17,47 @@
dependencies:
"@babel/highlight" "^7.10.4"
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a"
- integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.21.4":
+ version "7.21.4"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.21.4.tgz#d0fa9e4413aca81f2b23b9442797bda1826edb39"
+ integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==
dependencies:
"@babel/highlight" "^7.18.6"
-"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1":
- version "7.20.1"
- resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30"
- integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ==
+"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.21.5":
+ version "7.21.7"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.7.tgz#61caffb60776e49a57ba61a88f02bedd8714f6bc"
+ integrity sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==
"@babel/core@^7.1.0", "@babel/core@^7.12.3", "@babel/core@^7.18.10", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.2.tgz#8dc9b1620a673f92d3624bd926dc49a52cf25b92"
- integrity sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g==
- dependencies:
- "@ampproject/remapping" "^2.1.0"
- "@babel/code-frame" "^7.18.6"
- "@babel/generator" "^7.20.2"
- "@babel/helper-compilation-targets" "^7.20.0"
- "@babel/helper-module-transforms" "^7.20.2"
- "@babel/helpers" "^7.20.1"
- "@babel/parser" "^7.20.2"
- "@babel/template" "^7.18.10"
- "@babel/traverse" "^7.20.1"
- "@babel/types" "^7.20.2"
+ version "7.21.8"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.21.8.tgz#2a8c7f0f53d60100ba4c32470ba0281c92aa9aa4"
+ integrity sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==
+ dependencies:
+ "@ampproject/remapping" "^2.2.0"
+ "@babel/code-frame" "^7.21.4"
+ "@babel/generator" "^7.21.5"
+ "@babel/helper-compilation-targets" "^7.21.5"
+ "@babel/helper-module-transforms" "^7.21.5"
+ "@babel/helpers" "^7.21.5"
+ "@babel/parser" "^7.21.8"
+ "@babel/template" "^7.20.7"
+ "@babel/traverse" "^7.21.5"
+ "@babel/types" "^7.21.5"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
- json5 "^2.2.1"
+ json5 "^2.2.2"
semver "^6.3.0"
-"@babel/generator@^7.20.1", "@babel/generator@^7.20.2", "@babel/generator@^7.7.2":
- version "7.20.4"
- resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8"
- integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA==
+"@babel/generator@^7.21.5", "@babel/generator@^7.7.2":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.21.5.tgz#c0c0e5449504c7b7de8236d99338c3e2a340745f"
+ integrity sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==
dependencies:
- "@babel/types" "^7.20.2"
+ "@babel/types" "^7.21.5"
"@jridgewell/gen-mapping" "^0.3.2"
+ "@jridgewell/trace-mapping" "^0.3.17"
jsesc "^2.5.1"
"@babel/helper-annotate-as-pure@^7.18.6":
@@ -67,43 +68,46 @@
"@babel/types" "^7.18.6"
"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb"
- integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.21.5.tgz#817f73b6c59726ab39f6ba18c234268a519e5abb"
+ integrity sha512-uNrjKztPLkUk7bpCNC0jEKDJzzkvel/W+HguzbN8krA+LPfC1CEobJEvAvGka2A/M+ViOqXdcRL0GqPUJSjx9g==
dependencies:
- "@babel/helper-explode-assignable-expression" "^7.18.6"
- "@babel/types" "^7.18.9"
+ "@babel/types" "^7.21.5"
-"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0":
- version "7.20.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a"
- integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==
+"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.7", "@babel/helper-compilation-targets@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz#631e6cc784c7b660417421349aac304c94115366"
+ integrity sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==
dependencies:
- "@babel/compat-data" "^7.20.0"
- "@babel/helper-validator-option" "^7.18.6"
+ "@babel/compat-data" "^7.21.5"
+ "@babel/helper-validator-option" "^7.21.0"
browserslist "^4.21.3"
+ lru-cache "^5.1.1"
semver "^6.3.0"
-"@babel/helper-create-class-features-plugin@^7.18.6":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.2.tgz#3c08a5b5417c7f07b5cf3dfb6dc79cbec682e8c2"
- integrity sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA==
+"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0":
+ version "7.21.8"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.8.tgz#205b26330258625ef8869672ebca1e0dee5a0f02"
+ integrity sha512-+THiN8MqiH2AczyuZrnrKL6cAxFRRQDKW9h1YkBvbgKmAm6mwiacig1qT73DHIWMGo40GRnsEfN3LA+E6NtmSw==
dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6"
- "@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-function-name" "^7.19.0"
- "@babel/helper-member-expression-to-functions" "^7.18.9"
+ "@babel/helper-environment-visitor" "^7.21.5"
+ "@babel/helper-function-name" "^7.21.0"
+ "@babel/helper-member-expression-to-functions" "^7.21.5"
"@babel/helper-optimise-call-expression" "^7.18.6"
- "@babel/helper-replace-supers" "^7.19.1"
+ "@babel/helper-replace-supers" "^7.21.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0"
"@babel/helper-split-export-declaration" "^7.18.6"
+ semver "^6.3.0"
-"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0":
- version "7.19.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b"
- integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw==
+"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.20.5":
+ version "7.21.8"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.8.tgz#a7886f61c2e29e21fd4aaeaf1e473deba6b571dc"
+ integrity sha512-zGuSdedkFtsFHGbexAvNuipg1hbtitDLo2XE8/uf6Y9sOQV1xsYX/2pNbtedp/X0eU1pIt+kGvaqHCowkRbS5g==
dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6"
- regexpu-core "^5.1.0"
+ regexpu-core "^5.3.1"
+ semver "^6.3.0"
"@babel/helper-define-polyfill-provider@^0.3.3":
version "0.3.3"
@@ -117,25 +121,18 @@
resolve "^1.14.2"
semver "^6.1.2"
-"@babel/helper-environment-visitor@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
- integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
-
-"@babel/helper-explode-assignable-expression@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096"
- integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==
- dependencies:
- "@babel/types" "^7.18.6"
+"@babel/helper-environment-visitor@^7.18.9", "@babel/helper-environment-visitor@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz#c769afefd41d171836f7cb63e295bedf689d48ba"
+ integrity sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==
-"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0":
- version "7.19.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c"
- integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==
+"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0", "@babel/helper-function-name@^7.21.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz#d552829b10ea9f120969304023cd0645fa00b1b4"
+ integrity sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==
dependencies:
- "@babel/template" "^7.18.10"
- "@babel/types" "^7.19.0"
+ "@babel/template" "^7.20.7"
+ "@babel/types" "^7.21.0"
"@babel/helper-hoist-variables@^7.18.6":
version "7.18.6"
@@ -144,33 +141,33 @@
dependencies:
"@babel/types" "^7.18.6"
-"@babel/helper-member-expression-to-functions@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815"
- integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==
+"@babel/helper-member-expression-to-functions@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.5.tgz#3b1a009af932e586af77c1030fba9ee0bde396c0"
+ integrity sha512-nIcGfgwpH2u4n9GG1HpStW5Ogx7x7ekiFHbjjFRKXbn5zUvqO9ZgotCO4x1aNbKn/x/xOUaXEhyNHCwtFCpxWg==
dependencies:
- "@babel/types" "^7.18.9"
+ "@babel/types" "^7.21.5"
-"@babel/helper-module-imports@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e"
- integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==
+"@babel/helper-module-imports@^7.18.6", "@babel/helper-module-imports@^7.21.4":
+ version "7.21.4"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz#ac88b2f76093637489e718a90cec6cf8a9b029af"
+ integrity sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==
dependencies:
- "@babel/types" "^7.18.6"
+ "@babel/types" "^7.21.4"
-"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.2":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712"
- integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==
+"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.20.11", "@babel/helper-module-transforms@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz#d937c82e9af68d31ab49039136a222b17ac0b420"
+ integrity sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==
dependencies:
- "@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-module-imports" "^7.18.6"
- "@babel/helper-simple-access" "^7.20.2"
+ "@babel/helper-environment-visitor" "^7.21.5"
+ "@babel/helper-module-imports" "^7.21.4"
+ "@babel/helper-simple-access" "^7.21.5"
"@babel/helper-split-export-declaration" "^7.18.6"
"@babel/helper-validator-identifier" "^7.19.1"
- "@babel/template" "^7.18.10"
- "@babel/traverse" "^7.20.1"
- "@babel/types" "^7.20.2"
+ "@babel/template" "^7.20.7"
+ "@babel/traverse" "^7.21.5"
+ "@babel/types" "^7.21.5"
"@babel/helper-optimise-call-expression@^7.18.6":
version "7.18.6"
@@ -179,12 +176,12 @@
dependencies:
"@babel/types" "^7.18.6"
-"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629"
- integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.21.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz#345f2377d05a720a4e5ecfa39cbf4474a4daed56"
+ integrity sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==
-"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9":
+"@babel/helper-remap-async-to-generator@^7.18.9":
version "7.18.9"
resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519"
integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==
@@ -194,25 +191,26 @@
"@babel/helper-wrap-function" "^7.18.9"
"@babel/types" "^7.18.9"
-"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1":
- version "7.19.1"
- resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78"
- integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw==
+"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.20.7", "@babel/helper-replace-supers@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.21.5.tgz#a6ad005ba1c7d9bc2973dfde05a1bba7065dde3c"
+ integrity sha512-/y7vBgsr9Idu4M6MprbOVUfH3vs7tsIfnVWv/Ml2xgwvyH6LTngdfbf5AdsKwkJy4zgy1X/kuNrEKvhhK28Yrg==
dependencies:
- "@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-member-expression-to-functions" "^7.18.9"
+ "@babel/helper-environment-visitor" "^7.21.5"
+ "@babel/helper-member-expression-to-functions" "^7.21.5"
"@babel/helper-optimise-call-expression" "^7.18.6"
- "@babel/traverse" "^7.19.1"
- "@babel/types" "^7.19.0"
+ "@babel/template" "^7.20.7"
+ "@babel/traverse" "^7.21.5"
+ "@babel/types" "^7.21.5"
-"@babel/helper-simple-access@^7.19.4", "@babel/helper-simple-access@^7.20.2":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9"
- integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==
+"@babel/helper-simple-access@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz#d697a7971a5c39eac32c7e63c0921c06c8a249ee"
+ integrity sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==
dependencies:
- "@babel/types" "^7.20.2"
+ "@babel/types" "^7.21.5"
-"@babel/helper-skip-transparent-expression-wrappers@^7.18.9":
+"@babel/helper-skip-transparent-expression-wrappers@^7.20.0":
version "7.20.0"
resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684"
integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==
@@ -226,39 +224,39 @@
dependencies:
"@babel/types" "^7.18.6"
-"@babel/helper-string-parser@^7.19.4":
- version "7.19.4"
- resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63"
- integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==
+"@babel/helper-string-parser@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz#2b3eea65443c6bdc31c22d037c65f6d323b6b2bd"
+ integrity sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==
"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1":
version "7.19.1"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2"
integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==
-"@babel/helper-validator-option@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
- integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==
+"@babel/helper-validator-option@^7.21.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180"
+ integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==
"@babel/helper-wrap-function@^7.18.9":
- version "7.19.0"
- resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1"
- integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg==
+ version "7.20.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.20.5.tgz#75e2d84d499a0ab3b31c33bcfe59d6b8a45f62e3"
+ integrity sha512-bYMxIWK5mh+TgXGVqAtnu5Yn1un+v8DDZtqyzKRLUzrh70Eal2O3aZ7aPYiMADO4uKlkzOiRiZ6GX5q3qxvW9Q==
dependencies:
"@babel/helper-function-name" "^7.19.0"
"@babel/template" "^7.18.10"
- "@babel/traverse" "^7.19.0"
- "@babel/types" "^7.19.0"
+ "@babel/traverse" "^7.20.5"
+ "@babel/types" "^7.20.5"
-"@babel/helpers@^7.20.1":
- version "7.20.1"
- resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9"
- integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg==
+"@babel/helpers@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.21.5.tgz#5bac66e084d7a4d2d9696bdf0175a93f7fb63c08"
+ integrity sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==
dependencies:
- "@babel/template" "^7.18.10"
- "@babel/traverse" "^7.20.1"
- "@babel/types" "^7.20.0"
+ "@babel/template" "^7.20.7"
+ "@babel/traverse" "^7.21.5"
+ "@babel/types" "^7.21.5"
"@babel/highlight@^7.10.4", "@babel/highlight@^7.18.6":
version "7.18.6"
@@ -269,10 +267,10 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
-"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.18.10", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2":
- version "7.20.3"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2"
- integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg==
+"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.21.5", "@babel/parser@^7.21.8":
+ version "7.21.8"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.21.8.tgz#642af7d0333eab9c0ad70b14ac5e76dbde7bfdf8"
+ integrity sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
version "7.18.6"
@@ -281,22 +279,22 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50"
- integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==
+"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.20.7":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.20.7.tgz#d9c85589258539a22a901033853101a6198d4ef1"
+ integrity sha512-sbr9+wNE5aXMBBFBICk01tt7sBf2Oc9ikRFEcem/ZORup9IMUdNhW7/wVLEbbtlWOsEubJet46mHAL2C8+2jKQ==
dependencies:
- "@babel/helper-plugin-utils" "^7.18.9"
- "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
- "@babel/plugin-proposal-optional-chaining" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0"
+ "@babel/plugin-proposal-optional-chaining" "^7.20.7"
-"@babel/plugin-proposal-async-generator-functions@^7.20.1":
- version "7.20.1"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.1.tgz#352f02baa5d69f4e7529bdac39aaa02d41146af9"
- integrity sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g==
+"@babel/plugin-proposal-async-generator-functions@^7.20.7":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz#bfb7276d2d573cb67ba379984a2334e262ba5326"
+ integrity sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==
dependencies:
"@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-plugin-utils" "^7.20.2"
"@babel/helper-remap-async-to-generator" "^7.18.9"
"@babel/plugin-syntax-async-generators" "^7.8.4"
@@ -308,13 +306,13 @@
"@babel/helper-create-class-features-plugin" "^7.18.6"
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-proposal-class-static-block@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020"
- integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==
+"@babel/plugin-proposal-class-static-block@^7.21.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz#77bdd66fb7b605f3a61302d224bdfacf5547977d"
+ integrity sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==
dependencies:
- "@babel/helper-create-class-features-plugin" "^7.18.6"
- "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/helper-create-class-features-plugin" "^7.21.0"
+ "@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-class-static-block" "^7.14.5"
"@babel/plugin-proposal-dynamic-import@^7.18.6":
@@ -341,12 +339,12 @@
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-syntax-json-strings" "^7.8.3"
-"@babel/plugin-proposal-logical-assignment-operators@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23"
- integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==
+"@babel/plugin-proposal-logical-assignment-operators@^7.20.7":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz#dfbcaa8f7b4d37b51e8bfb46d94a5aea2bb89d83"
+ integrity sha512-y7C7cZgpMIjWlKE5T7eJwp+tnRYM89HmRvWM5EQuB5BoHEONjmQ8lSNmBUwOyy/GFRsohJED51YBF79hE1djug==
dependencies:
- "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6":
@@ -365,16 +363,16 @@
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-syntax-numeric-separator" "^7.10.4"
-"@babel/plugin-proposal-object-rest-spread@^7.20.2":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.2.tgz#a556f59d555f06961df1e572bb5eca864c84022d"
- integrity sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ==
+"@babel/plugin-proposal-object-rest-spread@^7.20.7":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz#aa662940ef425779c75534a5c41e9d936edc390a"
+ integrity sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==
dependencies:
- "@babel/compat-data" "^7.20.1"
- "@babel/helper-compilation-targets" "^7.20.0"
+ "@babel/compat-data" "^7.20.5"
+ "@babel/helper-compilation-targets" "^7.20.7"
"@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-object-rest-spread" "^7.8.3"
- "@babel/plugin-transform-parameters" "^7.20.1"
+ "@babel/plugin-transform-parameters" "^7.20.7"
"@babel/plugin-proposal-optional-catch-binding@^7.18.6":
version "7.18.6"
@@ -384,13 +382,13 @@
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
-"@babel/plugin-proposal-optional-chaining@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993"
- integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==
+"@babel/plugin-proposal-optional-chaining@^7.20.7", "@babel/plugin-proposal-optional-chaining@^7.21.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea"
+ integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==
dependencies:
- "@babel/helper-plugin-utils" "^7.18.9"
- "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0"
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
"@babel/plugin-proposal-private-methods@^7.18.6":
@@ -401,14 +399,14 @@
"@babel/helper-create-class-features-plugin" "^7.18.6"
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-proposal-private-property-in-object@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503"
- integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==
+"@babel/plugin-proposal-private-property-in-object@^7.21.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz#19496bd9883dd83c23c7d7fc45dcd9ad02dfa1dc"
+ integrity sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==
dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6"
- "@babel/helper-create-class-features-plugin" "^7.18.6"
- "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/helper-create-class-features-plugin" "^7.21.0"
+ "@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-syntax-private-property-in-object" "^7.14.5"
"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
@@ -468,7 +466,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.19.0"
-"@babel/plugin-syntax-import-meta@^7.8.3":
+"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51"
integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==
@@ -539,27 +537,27 @@
"@babel/helper-plugin-utils" "^7.14.5"
"@babel/plugin-syntax-typescript@^7.7.2":
- version "7.20.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7"
- integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==
+ version "7.21.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz#2751948e9b7c6d771a8efa59340c15d4a2891ff8"
+ integrity sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==
dependencies:
- "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-plugin-utils" "^7.20.2"
-"@babel/plugin-transform-arrow-functions@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe"
- integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==
+"@babel/plugin-transform-arrow-functions@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.21.5.tgz#9bb42a53de447936a57ba256fbf537fc312b6929"
+ integrity sha512-wb1mhwGOCaXHDTcsRYMKF9e5bbMgqwxtqa2Y1ifH96dXJPwbuLX9qHy3clhrxVqgMz7nyNXs8VkxdH8UBcjKqA==
dependencies:
- "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.21.5"
-"@babel/plugin-transform-async-to-generator@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615"
- integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==
+"@babel/plugin-transform-async-to-generator@^7.20.7":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz#dfee18623c8cb31deb796aa3ca84dda9cea94354"
+ integrity sha512-Uo5gwHPT9vgnSXQxqGtpdufUiWp96gk7yiP4Mp5bm1QMkEmLXBO7PAGYbKoJ6DhAwiNkcHFBol/x5zZZkL/t0Q==
dependencies:
"@babel/helper-module-imports" "^7.18.6"
- "@babel/helper-plugin-utils" "^7.18.6"
- "@babel/helper-remap-async-to-generator" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/helper-remap-async-to-generator" "^7.18.9"
"@babel/plugin-transform-block-scoped-functions@^7.18.6":
version "7.18.6"
@@ -568,39 +566,40 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-block-scoping@^7.20.2":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.2.tgz#f59b1767e6385c663fd0bce655db6ca9c8b236ed"
- integrity sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ==
+"@babel/plugin-transform-block-scoping@^7.21.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz#e737b91037e5186ee16b76e7ae093358a5634f02"
+ integrity sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==
dependencies:
"@babel/helper-plugin-utils" "^7.20.2"
-"@babel/plugin-transform-classes@^7.20.2":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.2.tgz#c0033cf1916ccf78202d04be4281d161f6709bb2"
- integrity sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g==
+"@babel/plugin-transform-classes@^7.21.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz#f469d0b07a4c5a7dbb21afad9e27e57b47031665"
+ integrity sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==
dependencies:
"@babel/helper-annotate-as-pure" "^7.18.6"
- "@babel/helper-compilation-targets" "^7.20.0"
+ "@babel/helper-compilation-targets" "^7.20.7"
"@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-function-name" "^7.19.0"
+ "@babel/helper-function-name" "^7.21.0"
"@babel/helper-optimise-call-expression" "^7.18.6"
"@babel/helper-plugin-utils" "^7.20.2"
- "@babel/helper-replace-supers" "^7.19.1"
+ "@babel/helper-replace-supers" "^7.20.7"
"@babel/helper-split-export-declaration" "^7.18.6"
globals "^11.1.0"
-"@babel/plugin-transform-computed-properties@^7.18.9":
- version "7.18.9"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e"
- integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==
+"@babel/plugin-transform-computed-properties@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.21.5.tgz#3a2d8bb771cd2ef1cd736435f6552fe502e11b44"
+ integrity sha512-TR653Ki3pAwxBxUe8srfF3e4Pe3FTA46uaNHYyQwIoM4oWKSoOZiDNyHJ0oIoDIUPSRQbQG7jzgVBX3FPVne1Q==
dependencies:
- "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.21.5"
+ "@babel/template" "^7.20.7"
-"@babel/plugin-transform-destructuring@^7.20.2":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.2.tgz#c23741cfa44ddd35f5e53896e88c75331b8b2792"
- integrity sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw==
+"@babel/plugin-transform-destructuring@^7.21.3":
+ version "7.21.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz#73b46d0fd11cd6ef57dea8a381b1215f4959d401"
+ integrity sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==
dependencies:
"@babel/helper-plugin-utils" "^7.20.2"
@@ -627,12 +626,12 @@
"@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6"
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-for-of@^7.18.8":
- version "7.18.8"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1"
- integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==
+"@babel/plugin-transform-for-of@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.5.tgz#e890032b535f5a2e237a18535f56a9fdaa7b83fc"
+ integrity sha512-nYWpjKW/7j/I/mZkGVgHJXh4bA1sfdFnJoOXwJuj4m3Q2EraO/8ZyrkCau9P5tbHQk01RMSt6KYLCsW7730SXQ==
dependencies:
- "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.21.5"
"@babel/plugin-transform-function-name@^7.18.9":
version "7.18.9"
@@ -657,31 +656,31 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-modules-amd@^7.19.6":
- version "7.19.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.19.6.tgz#aca391801ae55d19c4d8d2ebfeaa33df5f2a2cbd"
- integrity sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg==
+"@babel/plugin-transform-modules-amd@^7.20.11":
+ version "7.20.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.20.11.tgz#3daccca8e4cc309f03c3a0c4b41dc4b26f55214a"
+ integrity sha512-NuzCt5IIYOW0O30UvqktzHYR2ud5bOWbY0yaxWZ6G+aFzOMJvrs5YHNikrbdaT15+KNO31nPOy5Fim3ku6Zb5g==
dependencies:
- "@babel/helper-module-transforms" "^7.19.6"
- "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-module-transforms" "^7.20.11"
+ "@babel/helper-plugin-utils" "^7.20.2"
-"@babel/plugin-transform-modules-commonjs@^7.19.6":
- version "7.19.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz#25b32feef24df8038fc1ec56038917eacb0b730c"
- integrity sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ==
+"@babel/plugin-transform-modules-commonjs@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.5.tgz#d69fb947eed51af91de82e4708f676864e5e47bc"
+ integrity sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==
dependencies:
- "@babel/helper-module-transforms" "^7.19.6"
- "@babel/helper-plugin-utils" "^7.19.0"
- "@babel/helper-simple-access" "^7.19.4"
+ "@babel/helper-module-transforms" "^7.21.5"
+ "@babel/helper-plugin-utils" "^7.21.5"
+ "@babel/helper-simple-access" "^7.21.5"
-"@babel/plugin-transform-modules-systemjs@^7.19.6":
- version "7.19.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.6.tgz#59e2a84064b5736a4471b1aa7b13d4431d327e0d"
- integrity sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ==
+"@babel/plugin-transform-modules-systemjs@^7.20.11":
+ version "7.20.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.20.11.tgz#467ec6bba6b6a50634eea61c9c232654d8a4696e"
+ integrity sha512-vVu5g9BPQKSFEmvt2TA4Da5N+QVS66EX21d8uoOihC+OCpUoGvzVsXeqFdtAEfVa5BILAeFt+U7yVmLbQnAJmw==
dependencies:
"@babel/helper-hoist-variables" "^7.18.6"
- "@babel/helper-module-transforms" "^7.19.6"
- "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-module-transforms" "^7.20.11"
+ "@babel/helper-plugin-utils" "^7.20.2"
"@babel/helper-validator-identifier" "^7.19.1"
"@babel/plugin-transform-modules-umd@^7.18.6":
@@ -692,13 +691,13 @@
"@babel/helper-module-transforms" "^7.18.6"
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1":
- version "7.19.1"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888"
- integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw==
+"@babel/plugin-transform-named-capturing-groups-regex@^7.20.5":
+ version "7.20.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.20.5.tgz#626298dd62ea51d452c3be58b285d23195ba69a8"
+ integrity sha512-mOW4tTzi5iTLnw+78iEq3gr8Aoq4WNRGpmSlrogqaiCBoR1HFhpU4JkpQFOHfeYx3ReVIFWOQJS4aZBRvuZ6mA==
dependencies:
- "@babel/helper-create-regexp-features-plugin" "^7.19.0"
- "@babel/helper-plugin-utils" "^7.19.0"
+ "@babel/helper-create-regexp-features-plugin" "^7.20.5"
+ "@babel/helper-plugin-utils" "^7.20.2"
"@babel/plugin-transform-new-target@^7.18.6":
version "7.18.6"
@@ -715,10 +714,10 @@
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/helper-replace-supers" "^7.18.6"
-"@babel/plugin-transform-parameters@^7.20.1":
- version "7.20.3"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.3.tgz#7b3468d70c3c5b62e46be0a47b6045d8590fb748"
- integrity sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA==
+"@babel/plugin-transform-parameters@^7.20.7", "@babel/plugin-transform-parameters@^7.21.3":
+ version "7.21.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz#18fc4e797cf6d6d972cb8c411dbe8a809fa157db"
+ integrity sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==
dependencies:
"@babel/helper-plugin-utils" "^7.20.2"
@@ -729,13 +728,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-regenerator@^7.18.6":
- version "7.18.6"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73"
- integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==
+"@babel/plugin-transform-regenerator@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.21.5.tgz#576c62f9923f94bcb1c855adc53561fd7913724e"
+ integrity sha512-ZoYBKDb6LyMi5yCsByQ5jmXsHAQDDYeexT1Szvlmui+lADvfSecr5Dxd/PkrTC3pAD182Fcju1VQkB4oCp9M+w==
dependencies:
- "@babel/helper-plugin-utils" "^7.18.6"
- regenerator-transform "^0.15.0"
+ "@babel/helper-plugin-utils" "^7.21.5"
+ regenerator-transform "^0.15.1"
"@babel/plugin-transform-reserved-words@^7.18.6":
version "7.18.6"
@@ -751,13 +750,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.6"
-"@babel/plugin-transform-spread@^7.19.0":
- version "7.19.0"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6"
- integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w==
+"@babel/plugin-transform-spread@^7.20.7":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.20.7.tgz#c2d83e0b99d3bf83e07b11995ee24bf7ca09401e"
+ integrity sha512-ewBbHQ+1U/VnH1fxltbJqDeWBU1oNLG8Dj11uIv3xVf7nrQu0bPGe5Rf716r7K5Qz+SqtAOVswoVunoiBtGhxw==
dependencies:
- "@babel/helper-plugin-utils" "^7.19.0"
- "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0"
"@babel/plugin-transform-sticky-regex@^7.18.6":
version "7.18.6"
@@ -780,12 +779,12 @@
dependencies:
"@babel/helper-plugin-utils" "^7.18.9"
-"@babel/plugin-transform-unicode-escapes@^7.18.10":
- version "7.18.10"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246"
- integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==
+"@babel/plugin-transform-unicode-escapes@^7.21.5":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.21.5.tgz#1e55ed6195259b0e9061d81f5ef45a9b009fb7f2"
+ integrity sha512-LYm/gTOwZqsYohlvFUe/8Tujz75LqqVC2w+2qPHLR+WyWHGCZPN1KBpJCJn+4Bk4gOkQy/IXKIge6az5MqwlOg==
dependencies:
- "@babel/helper-plugin-utils" "^7.18.9"
+ "@babel/helper-plugin-utils" "^7.21.5"
"@babel/plugin-transform-unicode-regex@^7.18.6":
version "7.18.6"
@@ -796,30 +795,30 @@
"@babel/helper-plugin-utils" "^7.18.6"
"@babel/preset-env@^7.15.6":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506"
- integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==
- dependencies:
- "@babel/compat-data" "^7.20.1"
- "@babel/helper-compilation-targets" "^7.20.0"
- "@babel/helper-plugin-utils" "^7.20.2"
- "@babel/helper-validator-option" "^7.18.6"
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.21.5.tgz#db2089d99efd2297716f018aeead815ac3decffb"
+ integrity sha512-wH00QnTTldTbf/IefEVyChtRdw5RJvODT/Vb4Vcxq1AZvtXj6T0YeX0cAcXhI6/BdGuiP3GcNIL4OQbI2DVNxg==
+ dependencies:
+ "@babel/compat-data" "^7.21.5"
+ "@babel/helper-compilation-targets" "^7.21.5"
+ "@babel/helper-plugin-utils" "^7.21.5"
+ "@babel/helper-validator-option" "^7.21.0"
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6"
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9"
- "@babel/plugin-proposal-async-generator-functions" "^7.20.1"
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.20.7"
+ "@babel/plugin-proposal-async-generator-functions" "^7.20.7"
"@babel/plugin-proposal-class-properties" "^7.18.6"
- "@babel/plugin-proposal-class-static-block" "^7.18.6"
+ "@babel/plugin-proposal-class-static-block" "^7.21.0"
"@babel/plugin-proposal-dynamic-import" "^7.18.6"
"@babel/plugin-proposal-export-namespace-from" "^7.18.9"
"@babel/plugin-proposal-json-strings" "^7.18.6"
- "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9"
+ "@babel/plugin-proposal-logical-assignment-operators" "^7.20.7"
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6"
"@babel/plugin-proposal-numeric-separator" "^7.18.6"
- "@babel/plugin-proposal-object-rest-spread" "^7.20.2"
+ "@babel/plugin-proposal-object-rest-spread" "^7.20.7"
"@babel/plugin-proposal-optional-catch-binding" "^7.18.6"
- "@babel/plugin-proposal-optional-chaining" "^7.18.9"
+ "@babel/plugin-proposal-optional-chaining" "^7.21.0"
"@babel/plugin-proposal-private-methods" "^7.18.6"
- "@babel/plugin-proposal-private-property-in-object" "^7.18.6"
+ "@babel/plugin-proposal-private-property-in-object" "^7.21.0"
"@babel/plugin-proposal-unicode-property-regex" "^7.18.6"
"@babel/plugin-syntax-async-generators" "^7.8.4"
"@babel/plugin-syntax-class-properties" "^7.12.13"
@@ -827,6 +826,7 @@
"@babel/plugin-syntax-dynamic-import" "^7.8.3"
"@babel/plugin-syntax-export-namespace-from" "^7.8.3"
"@babel/plugin-syntax-import-assertions" "^7.20.0"
+ "@babel/plugin-syntax-import-meta" "^7.10.4"
"@babel/plugin-syntax-json-strings" "^7.8.3"
"@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
@@ -836,40 +836,40 @@
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
"@babel/plugin-syntax-private-property-in-object" "^7.14.5"
"@babel/plugin-syntax-top-level-await" "^7.14.5"
- "@babel/plugin-transform-arrow-functions" "^7.18.6"
- "@babel/plugin-transform-async-to-generator" "^7.18.6"
+ "@babel/plugin-transform-arrow-functions" "^7.21.5"
+ "@babel/plugin-transform-async-to-generator" "^7.20.7"
"@babel/plugin-transform-block-scoped-functions" "^7.18.6"
- "@babel/plugin-transform-block-scoping" "^7.20.2"
- "@babel/plugin-transform-classes" "^7.20.2"
- "@babel/plugin-transform-computed-properties" "^7.18.9"
- "@babel/plugin-transform-destructuring" "^7.20.2"
+ "@babel/plugin-transform-block-scoping" "^7.21.0"
+ "@babel/plugin-transform-classes" "^7.21.0"
+ "@babel/plugin-transform-computed-properties" "^7.21.5"
+ "@babel/plugin-transform-destructuring" "^7.21.3"
"@babel/plugin-transform-dotall-regex" "^7.18.6"
"@babel/plugin-transform-duplicate-keys" "^7.18.9"
"@babel/plugin-transform-exponentiation-operator" "^7.18.6"
- "@babel/plugin-transform-for-of" "^7.18.8"
+ "@babel/plugin-transform-for-of" "^7.21.5"
"@babel/plugin-transform-function-name" "^7.18.9"
"@babel/plugin-transform-literals" "^7.18.9"
"@babel/plugin-transform-member-expression-literals" "^7.18.6"
- "@babel/plugin-transform-modules-amd" "^7.19.6"
- "@babel/plugin-transform-modules-commonjs" "^7.19.6"
- "@babel/plugin-transform-modules-systemjs" "^7.19.6"
+ "@babel/plugin-transform-modules-amd" "^7.20.11"
+ "@babel/plugin-transform-modules-commonjs" "^7.21.5"
+ "@babel/plugin-transform-modules-systemjs" "^7.20.11"
"@babel/plugin-transform-modules-umd" "^7.18.6"
- "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.20.5"
"@babel/plugin-transform-new-target" "^7.18.6"
"@babel/plugin-transform-object-super" "^7.18.6"
- "@babel/plugin-transform-parameters" "^7.20.1"
+ "@babel/plugin-transform-parameters" "^7.21.3"
"@babel/plugin-transform-property-literals" "^7.18.6"
- "@babel/plugin-transform-regenerator" "^7.18.6"
+ "@babel/plugin-transform-regenerator" "^7.21.5"
"@babel/plugin-transform-reserved-words" "^7.18.6"
"@babel/plugin-transform-shorthand-properties" "^7.18.6"
- "@babel/plugin-transform-spread" "^7.19.0"
+ "@babel/plugin-transform-spread" "^7.20.7"
"@babel/plugin-transform-sticky-regex" "^7.18.6"
"@babel/plugin-transform-template-literals" "^7.18.9"
"@babel/plugin-transform-typeof-symbol" "^7.18.9"
- "@babel/plugin-transform-unicode-escapes" "^7.18.10"
+ "@babel/plugin-transform-unicode-escapes" "^7.21.5"
"@babel/plugin-transform-unicode-regex" "^7.18.6"
"@babel/preset-modules" "^0.1.5"
- "@babel/types" "^7.20.2"
+ "@babel/types" "^7.21.5"
babel-plugin-polyfill-corejs2 "^0.3.3"
babel-plugin-polyfill-corejs3 "^0.6.0"
babel-plugin-polyfill-regenerator "^0.4.1"
@@ -887,44 +887,49 @@
"@babel/types" "^7.4.4"
esutils "^2.0.2"
-"@babel/runtime@^7.8.4":
- version "7.20.1"
- resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9"
- integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg==
- dependencies:
- regenerator-runtime "^0.13.10"
+"@babel/regjsgen@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
+ integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
-"@babel/template@^7.18.10", "@babel/template@^7.3.3":
- version "7.18.10"
- resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71"
- integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==
+"@babel/runtime@^7.8.4":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200"
+ integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==
dependencies:
- "@babel/code-frame" "^7.18.6"
- "@babel/parser" "^7.18.10"
- "@babel/types" "^7.18.10"
+ regenerator-runtime "^0.13.11"
-"@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1", "@babel/traverse@^7.7.2":
- version "7.20.1"
- resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8"
- integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA==
+"@babel/template@^7.18.10", "@babel/template@^7.20.7", "@babel/template@^7.3.3":
+ version "7.20.7"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.20.7.tgz#a15090c2839a83b02aa996c0b4994005841fd5a8"
+ integrity sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==
dependencies:
"@babel/code-frame" "^7.18.6"
- "@babel/generator" "^7.20.1"
- "@babel/helper-environment-visitor" "^7.18.9"
- "@babel/helper-function-name" "^7.19.0"
+ "@babel/parser" "^7.20.7"
+ "@babel/types" "^7.20.7"
+
+"@babel/traverse@^7.20.5", "@babel/traverse@^7.21.5", "@babel/traverse@^7.7.2":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.21.5.tgz#ad22361d352a5154b498299d523cf72998a4b133"
+ integrity sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==
+ dependencies:
+ "@babel/code-frame" "^7.21.4"
+ "@babel/generator" "^7.21.5"
+ "@babel/helper-environment-visitor" "^7.21.5"
+ "@babel/helper-function-name" "^7.21.0"
"@babel/helper-hoist-variables" "^7.18.6"
"@babel/helper-split-export-declaration" "^7.18.6"
- "@babel/parser" "^7.20.1"
- "@babel/types" "^7.20.0"
+ "@babel/parser" "^7.21.5"
+ "@babel/types" "^7.21.5"
debug "^4.1.0"
globals "^11.1.0"
-"@babel/types@^7.0.0", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
- version "7.20.2"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.2.tgz#67ac09266606190f496322dbaff360fdaa5e7842"
- integrity sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog==
+"@babel/types@^7.0.0", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.20.0", "@babel/types@^7.20.5", "@babel/types@^7.20.7", "@babel/types@^7.21.0", "@babel/types@^7.21.4", "@babel/types@^7.21.5", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
+ version "7.21.5"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.21.5.tgz#18dfbd47c39d3904d5db3d3dc2cc80bedb60e5b6"
+ integrity sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==
dependencies:
- "@babel/helper-string-parser" "^7.19.4"
+ "@babel/helper-string-parser" "^7.21.5"
"@babel/helper-validator-identifier" "^7.19.1"
to-fast-properties "^2.0.0"
@@ -933,53 +938,55 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
-"@commitlint/config-validator@^17.1.0":
- version "17.1.0"
- resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-17.1.0.tgz#51d09ca53d7a0d19736abf34eb18a66efce0f97a"
- integrity sha512-Q1rRRSU09ngrTgeTXHq6ePJs2KrI+axPTgkNYDWSJIuS1Op4w3J30vUfSXjwn5YEJHklK3fSqWNHmBhmTR7Vdg==
+"@commitlint/config-validator@^17.4.4":
+ version "17.4.4"
+ resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-17.4.4.tgz#d0742705719559a101d2ee49c0c514044af6d64d"
+ integrity sha512-bi0+TstqMiqoBAQDvdEP4AFh0GaKyLFlPPEObgI29utoKEYoPQTvF0EYqIwYYLEoJYhj5GfMIhPHJkTJhagfeg==
dependencies:
- "@commitlint/types" "^17.0.0"
+ "@commitlint/types" "^17.4.4"
ajv "^8.11.0"
-"@commitlint/execute-rule@^17.0.0":
- version "17.0.0"
- resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-17.0.0.tgz#186e9261fd36733922ae617497888c4bdb6e5c92"
- integrity sha512-nVjL/w/zuqjCqSJm8UfpNaw66V9WzuJtQvEnCrK4jDw6qKTmZB+1JQ8m6BQVZbNBcwfYdDNKnhIhqI0Rk7lgpQ==
+"@commitlint/execute-rule@^17.4.0":
+ version "17.4.0"
+ resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz#4518e77958893d0a5835babe65bf87e2638f6939"
+ integrity sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==
"@commitlint/load@>6.1.1":
- version "17.2.0"
- resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-17.2.0.tgz#11c9fb23a967ff1507a28931c91aae7f978ea4ae"
- integrity sha512-HDD57qSqNrk399R4TIjw31AWBG8dBjNj1MrDKZKmC/wvimtnIFlqzcu1+sxfXIOHj/+M6tcMWDtvknGUd7SU+g==
- dependencies:
- "@commitlint/config-validator" "^17.1.0"
- "@commitlint/execute-rule" "^17.0.0"
- "@commitlint/resolve-extends" "^17.1.0"
- "@commitlint/types" "^17.0.0"
- "@types/node" "^14.0.0"
+ version "17.5.0"
+ resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-17.5.0.tgz#be45dbbb50aaf5eb7e8e940e1e0d6171d1426bab"
+ integrity sha512-l+4W8Sx4CD5rYFsrhHH8HP01/8jEP7kKf33Xlx2Uk2out/UKoKPYMOIRcDH5ppT8UXLMV+x6Wm5osdRKKgaD1Q==
+ dependencies:
+ "@commitlint/config-validator" "^17.4.4"
+ "@commitlint/execute-rule" "^17.4.0"
+ "@commitlint/resolve-extends" "^17.4.4"
+ "@commitlint/types" "^17.4.4"
+ "@types/node" "*"
chalk "^4.1.0"
- cosmiconfig "^7.0.0"
+ cosmiconfig "^8.0.0"
cosmiconfig-typescript-loader "^4.0.0"
- lodash "^4.17.19"
+ lodash.isplainobject "^4.0.6"
+ lodash.merge "^4.6.2"
+ lodash.uniq "^4.5.0"
resolve-from "^5.0.0"
ts-node "^10.8.1"
- typescript "^4.6.4"
+ typescript "^4.6.4 || ^5.0.0"
-"@commitlint/resolve-extends@^17.1.0":
- version "17.1.0"
- resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-17.1.0.tgz#7cf04fa13096c8a6544a4af13321fdf8d0d50694"
- integrity sha512-jqKm00LJ59T0O8O4bH4oMa4XyJVEOK4GzH8Qye9XKji+Q1FxhZznxMV/bDLyYkzbTodBt9sL0WLql8wMtRTbqQ==
+"@commitlint/resolve-extends@^17.4.4":
+ version "17.4.4"
+ resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-17.4.4.tgz#8f931467dea8c43b9fe38373e303f7c220de6fdc"
+ integrity sha512-znXr1S0Rr8adInptHw0JeLgumS11lWbk5xAWFVno+HUFVN45875kUtqjrI6AppmD3JI+4s0uZlqqlkepjJd99A==
dependencies:
- "@commitlint/config-validator" "^17.1.0"
- "@commitlint/types" "^17.0.0"
+ "@commitlint/config-validator" "^17.4.4"
+ "@commitlint/types" "^17.4.4"
import-fresh "^3.0.0"
- lodash "^4.17.19"
+ lodash.mergewith "^4.6.2"
resolve-from "^5.0.0"
resolve-global "^1.0.0"
-"@commitlint/types@^17.0.0":
- version "17.0.0"
- resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-17.0.0.tgz#3b4604c1a0f06c340ce976e6c6903d4f56e3e690"
- integrity sha512-hBAw6U+SkAT5h47zDMeOu3HSiD0SODw4Aq7rRNh1ceUmL7GyLKYhPbUvlRWqZ65XjBLPHZhFyQlRaPNz8qvUyQ==
+"@commitlint/types@^17.4.4":
+ version "17.4.4"
+ resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-17.4.4.tgz#1416df936e9aad0d6a7bbc979ecc31e55dade662"
+ integrity sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==
dependencies:
chalk "^4.1.0"
@@ -1574,38 +1581,40 @@
"@types/yargs" "^16.0.0"
chalk "^4.0.0"
-"@jridgewell/gen-mapping@^0.1.0":
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
- integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==
- dependencies:
- "@jridgewell/set-array" "^1.0.0"
- "@jridgewell/sourcemap-codec" "^1.4.10"
-
-"@jridgewell/gen-mapping@^0.3.2":
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
- integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
+"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
+ integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
dependencies:
"@jridgewell/set-array" "^1.0.1"
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping" "^0.3.9"
-"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3":
+"@jridgewell/resolve-uri@3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
-"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1":
+"@jridgewell/resolve-uri@^3.0.3":
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
+ integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==
+
+"@jridgewell/set-array@^1.0.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
-"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10":
+"@jridgewell/sourcemap-codec@1.4.14":
version "1.4.14"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
+"@jridgewell/sourcemap-codec@^1.4.10":
+ version "1.4.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+ integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
"@jridgewell/trace-mapping@0.3.9":
version "0.3.9"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
@@ -1614,14 +1623,22 @@
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"
-"@jridgewell/trace-mapping@^0.3.9":
- version "0.3.17"
- resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985"
- integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==
+"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9":
+ version "0.3.18"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6"
+ integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==
dependencies:
"@jridgewell/resolve-uri" "3.1.0"
"@jridgewell/sourcemap-codec" "1.4.14"
+"@morgan-stanley/ts-mocking-bird@^0.6.2":
+ version "0.6.4"
+ resolved "https://registry.yarnpkg.com/@morgan-stanley/ts-mocking-bird/-/ts-mocking-bird-0.6.4.tgz#2e4b60d42957bab3b50b67dbf14c3da2f62a39f7"
+ integrity sha512-57VJIflP8eR2xXa9cD1LUawh+Gh+BVQfVu0n6GALyg/AqV/Nz25kDRvws3i9kIe1PTrbsZZOYpsYp6bXPd6nVA==
+ dependencies:
+ lodash "^4.17.16"
+ uuid "^7.0.3"
+
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@@ -1655,10 +1672,10 @@
dependencies:
"@hapi/hoek" "^9.0.0"
-"@sideway/formula@^3.0.0":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.0.tgz#fe158aee32e6bd5de85044be615bc08478a0a13c"
- integrity sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==
+"@sideway/formula@^3.0.1":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
+ integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
"@sideway/pinpoint@^2.0.0":
version "2.0.0"
@@ -1666,9 +1683,9 @@
integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
"@sinonjs/commons@^1.7.0":
- version "1.8.5"
- resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.5.tgz#e280c94c95f206dcfd5aca00a43f2156b758c764"
- integrity sha512-rTpCA0wG1wUxglBSFdMMY0oTrKYvgf4fNgv/sXbfCVAdf+FnPBdKJR/7XbpTCwbCrvCbdPYnlWaUUYz4V2fPDA==
+ version "1.8.6"
+ resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9"
+ integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==
dependencies:
type-detect "4.0.8"
@@ -1731,12 +1748,12 @@
ts-essentials "^7.0.1"
"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14":
- version "7.1.20"
- resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.20.tgz#e168cdd612c92a2d335029ed62ac94c95b362359"
- integrity sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==
+ version "7.20.0"
+ resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.0.tgz#61bc5a4cae505ce98e1e36c5445e4bee060d8891"
+ integrity sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==
dependencies:
- "@babel/parser" "^7.1.0"
- "@babel/types" "^7.0.0"
+ "@babel/parser" "^7.20.7"
+ "@babel/types" "^7.20.7"
"@types/babel__generator" "*"
"@types/babel__template" "*"
"@types/babel__traverse" "*"
@@ -1757,16 +1774,16 @@
"@babel/types" "^7.0.0"
"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6":
- version "7.18.2"
- resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.2.tgz#235bf339d17185bdec25e024ca19cce257cc7309"
- integrity sha512-FcFaxOr2V5KZCviw1TnutEMVUVsGt4D2hP1TAfXZAMKuHYW3xQhe3jTxNPWutgCJ3/X1c5yX8ZoGVEItxKbwBg==
+ version "7.18.5"
+ resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.18.5.tgz#c107216842905afafd3b6e774f6f935da6f5db80"
+ integrity sha512-enCvTL8m/EHS/zIvJno9nE+ndYPh1/oNFzRYRmtUqJICG2VnCSBzMLW5VN2KCQU91f23tsNKR8v7VJJQMatl7Q==
dependencies:
"@babel/types" "^7.3.0"
"@types/graceful-fs@^4.1.2":
- version "4.1.5"
- resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15"
- integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==
+ version "4.1.6"
+ resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae"
+ integrity sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==
dependencies:
"@types/node" "*"
@@ -1813,29 +1830,19 @@
integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==
"@types/node@*":
- version "18.11.9"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4"
- integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==
-
-"@types/node@^14.0.0":
- version "14.18.33"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.33.tgz#8c29a0036771569662e4635790ffa9e057db379b"
- integrity sha512-qelS/Ra6sacc4loe/3MSjXNL1dNQ/GjxNHVzuChwMfmk7HuycRLVQN2qNY3XahK+fZc5E2szqQSKUyAF0E+2bg==
+ version "18.16.3"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.16.3.tgz#6bda7819aae6ea0b386ebc5b24bdf602f1b42b01"
+ integrity sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==
"@types/normalize-package-data@^2.4.0":
version "2.4.1"
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
integrity sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==
-"@types/parse-json@^4.0.0":
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
- integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
-
"@types/prettier@^2.1.1", "@types/prettier@^2.1.5":
- version "2.7.1"
- resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.1.tgz#dfd20e2dc35f027cdd6c1908e80a5ddc7499670e"
- integrity sha512-ri0UmynRRvZiiUJdiz38MmIblKK+oH30MztdBVR95dv/Ubw6neWSb8u1XpRb72L4qsZOhz+L+z9JD40SJmfWow==
+ version "2.7.2"
+ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.2.tgz#6c2324641cc4ba050a8c710b2b251b377581fbf0"
+ integrity sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==
"@types/qs@^6.9.7":
version "6.9.7"
@@ -1853,16 +1860,16 @@
integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==
"@types/yargs@^15.0.0":
- version "15.0.14"
- resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06"
- integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==
+ version "15.0.15"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.15.tgz#e609a2b1ef9e05d90489c2f5f45bbfb2be092158"
+ integrity sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg==
dependencies:
"@types/yargs-parser" "*"
"@types/yargs@^16.0.0":
- version "16.0.4"
- resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977"
- integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==
+ version "16.0.5"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.5.tgz#12cc86393985735a283e387936398c2f9e5f88e3"
+ integrity sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==
dependencies:
"@types/yargs-parser" "*"
@@ -1978,9 +1985,9 @@ acorn@^7.1.1, acorn@^7.4.0:
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
acorn@^8.2.4, acorn@^8.4.1:
- version "8.8.1"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73"
- integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==
+ version "8.8.2"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
+ integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
add-stream@^1.0.0:
version "1.0.0"
@@ -2010,9 +2017,9 @@ ajv@^6.10.0, ajv@^6.12.4:
uri-js "^4.2.2"
ajv@^8.0.1, ajv@^8.11.0:
- version "8.11.2"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78"
- integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg==
+ version "8.12.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
+ integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
dependencies:
fast-deep-equal "^3.1.1"
json-schema-traverse "^1.0.0"
@@ -2056,9 +2063,9 @@ ansi-styles@^5.0.0:
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
anymatch@^3.0.3:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
- integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
dependencies:
normalize-path "^3.0.0"
picomatch "^2.0.4"
@@ -2075,6 +2082,11 @@ argparse@^1.0.7:
dependencies:
sprintf-js "~1.0.2"
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
array-back@^3.0.1, array-back@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/array-back/-/array-back-3.1.0.tgz#b8859d7a508871c9a7b2cf42f99428f65e96bfb0"
@@ -2085,12 +2097,20 @@ array-back@^4.0.1, array-back@^4.0.2:
resolved "https://registry.yarnpkg.com/array-back/-/array-back-4.0.2.tgz#8004e999a6274586beeb27342168652fdb89fa1e"
integrity sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==
+array-buffer-byte-length@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead"
+ integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==
+ dependencies:
+ call-bind "^1.0.2"
+ is-array-buffer "^3.0.1"
+
array-ify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==
-array-includes@^3.1.4:
+array-includes@^3.1.6:
version "3.1.6"
resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f"
integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==
@@ -2118,7 +2138,7 @@ array-uniq@^1.0.1:
resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6"
integrity sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==
-array.prototype.flat@^1.2.5:
+array.prototype.flat@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2"
integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==
@@ -2128,6 +2148,16 @@ array.prototype.flat@^1.2.5:
es-abstract "^1.20.4"
es-shim-unscopables "^1.0.0"
+array.prototype.flatmap@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183"
+ integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ es-shim-unscopables "^1.0.0"
+
arrify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
@@ -2155,6 +2185,11 @@ at-least-node@^1.0.0:
resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
+available-typed-arrays@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
+ integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
+
axios@^0.21.1:
version "0.21.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
@@ -2313,15 +2348,15 @@ browser-process-hrtime@^1.0.0:
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
-browserslist@^4.21.3, browserslist@^4.21.4:
- version "4.21.4"
- resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987"
- integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==
+browserslist@^4.21.3, browserslist@^4.21.5:
+ version "4.21.5"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.5.tgz#75c5dae60063ee641f977e00edd3cfb2fb7af6a7"
+ integrity sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==
dependencies:
- caniuse-lite "^1.0.30001400"
- electron-to-chromium "^1.4.251"
- node-releases "^2.0.6"
- update-browserslist-db "^1.0.9"
+ caniuse-lite "^1.0.30001449"
+ electron-to-chromium "^1.4.284"
+ node-releases "^2.0.8"
+ update-browserslist-db "^1.0.10"
bs-logger@0.x:
version "0.2.6"
@@ -2387,10 +2422,10 @@ camelcase@^6.2.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
-caniuse-lite@^1.0.30001400:
- version "1.0.30001431"
- resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz#e7c59bd1bc518fae03a4656be442ce6c4887a795"
- integrity sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ==
+caniuse-lite@^1.0.30001449:
+ version "1.0.30001482"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001482.tgz#8b3fad73dc35b2674a5c96df2d4f9f1c561435de"
+ integrity sha512-F1ZInsg53cegyjroxLNW9DmrEQ1SuGRTO1QlpA0o2/6OpQ0gFeDRoq1yFmnr8Sakn9qwwt9DmbxHB6w167OSuQ==
chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
version "2.4.2"
@@ -2420,9 +2455,9 @@ chardet@^0.7.0:
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
ci-info@^3.2.0:
- version "3.6.1"
- resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.6.1.tgz#7594f1c95cb7fdfddee7af95a13af7dbc67afdcf"
- integrity sha512-up5ggbaDqOqJ4UqLKZ2naVkyqSJQgJi5lwD6b6mM748ysrghDBX0bx/qJTUHzw7zu6Mq4gycviSF5hJnwceD8w==
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91"
+ integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==
cjs-module-lexer@^1.0.0:
version "1.2.2"
@@ -2437,9 +2472,9 @@ cli-cursor@^3.1.0:
restore-cursor "^3.1.0"
cli-spinners@^2.5.0:
- version "2.7.0"
- resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a"
- integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.0.tgz#5881d0ad96381e117bbe07ad91f2008fe6ffd8db"
+ integrity sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==
cli-width@^3.0.0:
version "3.0.0"
@@ -2527,9 +2562,9 @@ commander@^2.18.0:
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
commitizen@^4.0.3:
- version "4.2.5"
- resolved "https://registry.yarnpkg.com/commitizen/-/commitizen-4.2.5.tgz#48e5a5c28334c6e8ed845cc24fc9f072efd3961e"
- integrity sha512-9sXju8Qrz1B4Tw7kC5KhnvwYQN88qs2zbiB8oyMsnXZyJ24PPGiNM3nHr73d32dnE3i8VJEXddBFIbOgYSEXtQ==
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/commitizen/-/commitizen-4.3.0.tgz#0d056c542a2d2b1f9b9aba981aa32575b2849924"
+ integrity sha512-H0iNtClNEhT0fotHvGV3E9tDejDeS04sN1veIebsKYGMuGscFaswRoYJKmT3eW85eIJAs0F28bG2+a/9wCOfPw==
dependencies:
cachedir "2.3.0"
cz-conventional-changelog "3.3.0"
@@ -2539,10 +2574,10 @@ commitizen@^4.0.3:
find-root "1.1.0"
fs-extra "9.1.0"
glob "7.2.3"
- inquirer "8.2.4"
+ inquirer "8.2.5"
is-utf8 "^0.2.1"
lodash "4.17.21"
- minimist "1.2.6"
+ minimist "1.2.7"
strip-bom "4.0.0"
strip-json-comments "3.1.1"
@@ -2748,11 +2783,11 @@ convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
core-js-compat@^3.25.1:
- version "3.26.1"
- resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.26.1.tgz#0e710b09ebf689d719545ac36e49041850f943df"
- integrity sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A==
+ version "3.30.1"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.30.1.tgz#961541e22db9c27fc48bfc13a3cafa8734171dfe"
+ integrity sha512-d690npR7MC6P0gq4npTl5n2VQeNAmUrJ90n+MHiKS7W2+xno4o3F5GDEuylSdi6EJ3VssibSGXOa1r3YXD3Mhw==
dependencies:
- browserslist "^4.21.4"
+ browserslist "^4.21.5"
core-util-is@~1.0.0:
version "1.0.3"
@@ -2760,20 +2795,19 @@ core-util-is@~1.0.0:
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
cosmiconfig-typescript-loader@^4.0.0:
- version "4.2.0"
- resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.2.0.tgz#a3cfd0dd9dac86be7dbe5f53eb46ad03abdf417b"
- integrity sha512-NkANeMnaHrlaSSlpKGyvn2R4rqUDeE/9E5YHx+b4nwo0R8dZyAqcih8/gxpCZvqWP9Vf6xuLpMSzSgdVEIM78g==
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.3.0.tgz#c4259ce474c9df0f32274ed162c0447c951ef073"
+ integrity sha512-NTxV1MFfZDLPiBMjxbHRwSh5LaLcPMwNdCutmnHJCKoVnlvldPWlllonKwrsRJ5pYZBIBGRWWU2tfvzxgeSW5Q==
-cosmiconfig@^7.0.0:
- version "7.1.0"
- resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6"
- integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
+cosmiconfig@^8.0.0:
+ version "8.1.3"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.1.3.tgz#0e614a118fcc2d9e5afc2f87d53cd09931015689"
+ integrity sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==
dependencies:
- "@types/parse-json" "^4.0.0"
import-fresh "^3.2.1"
+ js-yaml "^4.1.0"
parse-json "^5.0.0"
path-type "^4.0.0"
- yaml "^1.10.0"
create-require@^1.1.0:
version "1.1.1"
@@ -2857,13 +2891,6 @@ debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1:
dependencies:
ms "2.1.2"
-debug@^2.6.9:
- version "2.6.9"
- resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
- integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
- dependencies:
- ms "2.0.0"
-
debug@^3.2.7:
version "3.2.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
@@ -2885,9 +2912,9 @@ decamelize@^1.1.0, decamelize@^1.2.0:
integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
decimal.js@^10.2.1:
- version "10.4.2"
- resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.2.tgz#0341651d1d997d86065a2ce3a441fbd0d8e8b98e"
- integrity sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==
+ version "10.4.3"
+ resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23"
+ integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
dedent@0.7.0, dedent@^0.7.0:
version "0.7.0"
@@ -2905,9 +2932,9 @@ deep-is@^0.1.3, deep-is@~0.1.3:
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
deepmerge@^4.2.2:
- version "4.2.2"
- resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
- integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
+ integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
defaults@^1.0.3:
version "1.0.4"
@@ -2916,10 +2943,10 @@ defaults@^1.0.3:
dependencies:
clone "^1.0.2"
-define-properties@^1.1.3, define-properties@^1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
- integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
+define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5"
+ integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==
dependencies:
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
@@ -3002,10 +3029,10 @@ dotgitignore@^2.1.0:
find-up "^3.0.0"
minimatch "^3.0.4"
-electron-to-chromium@^1.4.251:
- version "1.4.284"
- resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592"
- integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==
+electron-to-chromium@^1.4.284:
+ version "1.4.382"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.382.tgz#87e659b0f0d5f7b19759038871bac0a327191f82"
+ integrity sha512-czMavlW52VIPgutbVL9JnZIZuFijzsG1ww/1z2Otu1r1q+9Qe2bTsH3My3sZarlvwyqHM6+mnZfEnt2Vr4dsIg==
elliptic@6.5.4:
version "6.5.4"
@@ -3050,34 +3077,53 @@ error-ex@^1.3.1:
is-arrayish "^0.2.1"
es-abstract@^1.19.0, es-abstract@^1.20.4:
- version "1.20.4"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.4.tgz#1d103f9f8d78d4cf0713edcd6d0ed1a46eed5861"
- integrity sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==
+ version "1.21.2"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff"
+ integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==
dependencies:
+ array-buffer-byte-length "^1.0.0"
+ available-typed-arrays "^1.0.5"
call-bind "^1.0.2"
+ es-set-tostringtag "^2.0.1"
es-to-primitive "^1.2.1"
- function-bind "^1.1.1"
function.prototype.name "^1.1.5"
- get-intrinsic "^1.1.3"
+ get-intrinsic "^1.2.0"
get-symbol-description "^1.0.0"
+ globalthis "^1.0.3"
+ gopd "^1.0.1"
has "^1.0.3"
has-property-descriptors "^1.0.0"
+ has-proto "^1.0.1"
has-symbols "^1.0.3"
- internal-slot "^1.0.3"
+ internal-slot "^1.0.5"
+ is-array-buffer "^3.0.2"
is-callable "^1.2.7"
is-negative-zero "^2.0.2"
is-regex "^1.1.4"
is-shared-array-buffer "^1.0.2"
is-string "^1.0.7"
+ is-typed-array "^1.1.10"
is-weakref "^1.0.2"
- object-inspect "^1.12.2"
+ object-inspect "^1.12.3"
object-keys "^1.1.1"
object.assign "^4.1.4"
regexp.prototype.flags "^1.4.3"
safe-regex-test "^1.0.0"
- string.prototype.trimend "^1.0.5"
- string.prototype.trimstart "^1.0.5"
+ string.prototype.trim "^1.2.7"
+ string.prototype.trimend "^1.0.6"
+ string.prototype.trimstart "^1.0.6"
+ typed-array-length "^1.0.4"
unbox-primitive "^1.0.2"
+ which-typed-array "^1.1.9"
+
+es-set-tostringtag@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
+ integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==
+ dependencies:
+ get-intrinsic "^1.1.3"
+ has "^1.0.3"
+ has-tostringtag "^1.0.0"
es-shim-unscopables@^1.0.0:
version "1.0.0"
@@ -3134,18 +3180,19 @@ eslint-config-prettier@^6.11.0:
dependencies:
get-stdin "^6.0.0"
-eslint-import-resolver-node@^0.3.6:
- version "0.3.6"
- resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd"
- integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==
+eslint-import-resolver-node@^0.3.7:
+ version "0.3.7"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7"
+ integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==
dependencies:
debug "^3.2.7"
- resolve "^1.20.0"
+ is-core-module "^2.11.0"
+ resolve "^1.22.1"
-eslint-module-utils@^2.7.3:
- version "2.7.4"
- resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz#4f3e41116aaf13a20792261e61d3a2e7e0583974"
- integrity sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==
+eslint-module-utils@^2.7.4:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49"
+ integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==
dependencies:
debug "^3.2.7"
@@ -3158,22 +3205,24 @@ eslint-plugin-eslint-comments@^3.2.0:
ignore "^5.0.5"
eslint-plugin-import@^2.22.0:
- version "2.26.0"
- resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b"
- integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==
+ version "2.27.5"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65"
+ integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==
dependencies:
- array-includes "^3.1.4"
- array.prototype.flat "^1.2.5"
- debug "^2.6.9"
+ array-includes "^3.1.6"
+ array.prototype.flat "^1.3.1"
+ array.prototype.flatmap "^1.3.1"
+ debug "^3.2.7"
doctrine "^2.1.0"
- eslint-import-resolver-node "^0.3.6"
- eslint-module-utils "^2.7.3"
+ eslint-import-resolver-node "^0.3.7"
+ eslint-module-utils "^2.7.4"
has "^1.0.3"
- is-core-module "^2.8.1"
+ is-core-module "^2.11.0"
is-glob "^4.0.3"
minimatch "^3.1.2"
- object.values "^1.1.5"
- resolve "^1.22.0"
+ object.values "^1.1.6"
+ resolve "^1.22.1"
+ semver "^6.3.0"
tsconfig-paths "^3.14.1"
eslint-scope@^5.1.1:
@@ -3269,9 +3318,9 @@ esprima@^4.0.0, esprima@^4.0.1:
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
esquery@^1.4.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
- integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
+ integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
dependencies:
estraverse "^5.1.0"
@@ -3406,9 +3455,9 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
fastq@^1.6.0:
- version "1.13.0"
- resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
- integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
+ integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
dependencies:
reusify "^1.0.4"
@@ -3419,10 +3468,10 @@ fb-watchman@^2.0.0:
dependencies:
bser "2.1.1"
-ferveo-wasm@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/ferveo-wasm/-/ferveo-wasm-0.1.0.tgz#03fa787ed1978f457d4847282d864778a3799f21"
- integrity sha512-KcPU0QVU/GkXoDeL8mG63Mm6kKyCECmMyF4QGnPqcCSeEXVY+sno67Vk98I/1b372QWsjye/6Rm5J5HBI8icCQ==
+ferveo-wasm@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/ferveo-wasm/-/ferveo-wasm-0.1.1.tgz#40419ed3eeab795abb929d5fb5806e300e363847"
+ integrity sha512-xaYOIrX6VT1rdjbMvykLH9exU9mmlxa8z26LHnnD2HYMoH14/fpC3R7QBFWsOXi2xlHbQd2x28iD7/p9bdBo4A==
figures@^3.0.0, figures@^3.1.0:
version "3.2.0"
@@ -3556,6 +3605,13 @@ follow-redirects@^1.14.0:
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
+for-each@^0.3.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
+ integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==
+ dependencies:
+ is-callable "^1.1.3"
+
form-data@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
@@ -3623,7 +3679,7 @@ functional-red-black-tree@^1.0.1:
resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==
-functions-have-names@^1.2.2:
+functions-have-names@^1.2.2, functions-have-names@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
@@ -3638,10 +3694,10 @@ get-caller-file@^2.0.5:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
-get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385"
- integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f"
+ integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==
dependencies:
function-bind "^1.1.1"
has "^1.0.3"
@@ -3752,9 +3808,9 @@ glob@7.2.3, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glo
path-is-absolute "^1.0.0"
glob@^8.0.3:
- version "8.0.3"
- resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e"
- integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
+ integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
@@ -3795,12 +3851,19 @@ globals@^11.1.0:
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
globals@^13.6.0, globals@^13.9.0:
- version "13.17.0"
- resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4"
- integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==
+ version "13.20.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82"
+ integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==
dependencies:
type-fest "^0.20.2"
+globalthis@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
+ integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
+ dependencies:
+ define-properties "^1.1.3"
+
globby@^11.0.3:
version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
@@ -3824,10 +3887,17 @@ globby@^6.1.0:
pify "^2.0.0"
pinkie-promise "^2.0.0"
+gopd@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
+ integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
+ dependencies:
+ get-intrinsic "^1.1.3"
+
graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.9:
- version "4.2.10"
- resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
- integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
handlebars@^4.7.7:
version "4.7.7"
@@ -3868,6 +3938,11 @@ has-property-descriptors@^1.0.0:
dependencies:
get-intrinsic "^1.1.1"
+has-proto@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
+ integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
+
has-symbols@^1.0.2, has-symbols@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
@@ -3980,9 +4055,9 @@ ignore@^4.0.6:
integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==
ignore@^5.0.5, ignore@^5.1.8, ignore@^5.2.0:
- version "5.2.0"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
- integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
+ version "5.2.4"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
+ integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
import-fresh@^3.0.0, import-fresh@^3.2.1:
version "3.3.0"
@@ -4028,10 +4103,10 @@ ini@^1.3.2, ini@^1.3.4:
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
-inquirer@8.2.4:
- version "8.2.4"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.4.tgz#ddbfe86ca2f67649a67daa6f1051c128f684f0b4"
- integrity sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==
+inquirer@8.2.5:
+ version "8.2.5"
+ resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.5.tgz#d8654a7542c35a9b9e069d27e2df4858784d54f8"
+ integrity sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==
dependencies:
ansi-escapes "^4.2.1"
chalk "^4.1.1"
@@ -4049,15 +4124,24 @@ inquirer@8.2.4:
through "^2.3.6"
wrap-ansi "^7.0.0"
-internal-slot@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
- integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==
+internal-slot@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986"
+ integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==
dependencies:
- get-intrinsic "^1.1.0"
+ get-intrinsic "^1.2.0"
has "^1.0.3"
side-channel "^1.0.4"
+is-array-buffer@^3.0.1, is-array-buffer@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe"
+ integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.2.0"
+ is-typed-array "^1.1.10"
+
is-arrayish@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
@@ -4078,15 +4162,15 @@ is-boolean-object@^1.1.0:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"
-is-callable@^1.1.4, is-callable@^1.2.7:
+is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
-is-core-module@^2.5.0, is-core-module@^2.8.1, is-core-module@^2.9.0:
- version "2.11.0"
- resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144"
- integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==
+is-core-module@^2.11.0, is-core-module@^2.5.0:
+ version "2.12.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.0.tgz#36ad62f6f73c8253fd6472517a12483cf03e7ec4"
+ integrity sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==
dependencies:
has "^1.0.3"
@@ -4202,6 +4286,17 @@ is-text-path@^1.0.1:
dependencies:
text-extensions "^1.0.0"
+is-typed-array@^1.1.10, is-typed-array@^1.1.9:
+ version "1.1.10"
+ resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f"
+ integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==
+ dependencies:
+ available-typed-arrays "^1.0.5"
+ call-bind "^1.0.2"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ has-tostringtag "^1.0.0"
+
is-typedarray@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
@@ -4528,9 +4623,9 @@ jest-mock@^27.5.1:
"@types/node" "*"
jest-pnp-resolver@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c"
- integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e"
+ integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==
jest-regex-util@^27.5.1:
version "27.5.1"
@@ -4709,14 +4804,14 @@ jest@^27.0.6:
jest-cli "^27.5.1"
joi@^17.7.0:
- version "17.7.0"
- resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.0.tgz#591a33b1fe1aca2bc27f290bcad9b9c1c570a6b3"
- integrity sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg==
+ version "17.9.2"
+ resolved "https://registry.yarnpkg.com/joi/-/joi-17.9.2.tgz#8b2e4724188369f55451aebd1d0b1d9482470690"
+ integrity sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==
dependencies:
"@hapi/hoek" "^9.0.0"
"@hapi/topo" "^5.0.0"
"@sideway/address" "^4.1.3"
- "@sideway/formula" "^3.0.0"
+ "@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
js-sha3@0.8.0, js-sha3@^0.8.0:
@@ -4737,6 +4832,13 @@ js-yaml@^3.13.1:
argparse "^1.0.7"
esprima "^4.0.0"
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
jsdom@^16.6.0:
version "16.7.0"
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710"
@@ -4810,12 +4912,12 @@ json-stringify-safe@^5.0.1:
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
-json5@2.x, json5@^2.2.1:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
- integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
+json5@2.x, json5@^2.2.2:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
+ integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
-json5@^1.0.1:
+json5@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
@@ -4944,6 +5046,11 @@ lodash.ismatch@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==
+lodash.isplainobject@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+ integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
+
lodash.map@^4.5.1:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
@@ -4959,12 +5066,22 @@ lodash.merge@^4.6.2:
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+lodash.mergewith@^4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
+ integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
+
lodash.truncate@^4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==
-lodash@4.17.21, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.7.0:
+lodash.uniq@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+ integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
+
+lodash@4.17.21, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.16, lodash@^4.17.21, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -4982,6 +5099,13 @@ longest@^2.0.1:
resolved "https://registry.yarnpkg.com/longest/-/longest-2.0.1.tgz#781e183296aa94f6d4d916dc335d0d17aefa23f8"
integrity sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -5024,9 +5148,9 @@ map-obj@^4.0.0:
integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==
marked@^4.0.16:
- version "4.2.2"
- resolved "https://registry.yarnpkg.com/marked/-/marked-4.2.2.tgz#1d2075ad6cdfe42e651ac221c32d949a26c0672a"
- integrity sha512-JjBTFTAvuTgANXx82a5vzK9JLSMoV6V3LBVn4Uhdso6t7vXrGx7g1Cd2r6NYSsxrYbQGFCMqBDhFHyK5q2UvcQ==
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3"
+ integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==
memorystream@^0.3.1:
version "0.3.1"
@@ -5130,9 +5254,9 @@ minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
brace-expansion "^1.1.7"
minimatch@^5.0.1, minimatch@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7"
- integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==
+ version "5.1.6"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
+ integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
dependencies:
brace-expansion "^2.0.1"
@@ -5145,16 +5269,16 @@ minimist-options@4.1.0, minimist-options@^4.0.2:
is-plain-obj "^1.1.0"
kind-of "^6.0.3"
-minimist@1.2.6:
- version "1.2.6"
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
- integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
-
-minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
+minimist@1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18"
integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==
+minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
mkdirp@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
@@ -5165,11 +5289,6 @@ modify-values@^1.0.0:
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
-ms@2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
- integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
-
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
@@ -5205,10 +5324,10 @@ node-int64@^0.4.0:
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==
-node-releases@^2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
- integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
+node-releases@^2.0.8:
+ version "2.0.10"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.10.tgz#c311ebae3b6a148c89b1813fd7c4d3c024ef537f"
+ integrity sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==
normalize-package-data@^2.3.2, normalize-package-data@^2.5.0:
version "2.5.0"
@@ -5258,19 +5377,19 @@ npm-run-path@^4.0.1:
path-key "^3.0.0"
nwsapi@^2.2.0:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.2.tgz#e5418863e7905df67d51ec95938d67bf801f0bb0"
- integrity sha512-90yv+6538zuvUMnN+zCr8LuV6bPFdq50304114vJYJ8RDyK8D5O9Phpbd6SZWgI7PwzmmfN1upeOJlvybDSgCw==
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.4.tgz#fd59d5e904e8e1f03c25a7d5a15cfa16c714a1e5"
+ integrity sha512-NHj4rzRo0tQdijE9ZqAx6kYDcoRwYwSYzCA8MY3JzfxlrvEU0jhnhJT9BhqhJs7I/dKcrDm6TyulaRqZPIhN5g==
object-assign@^4.0.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
-object-inspect@^1.12.2, object-inspect@^1.9.0:
- version "1.12.2"
- resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
- integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
+object-inspect@^1.12.3, object-inspect@^1.9.0:
+ version "1.12.3"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
+ integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
object-keys@^1.1.1:
version "1.1.1"
@@ -5287,7 +5406,7 @@ object.assign@^4.1.4:
has-symbols "^1.0.3"
object-keys "^1.1.1"
-object.values@^1.1.5:
+object.values@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d"
integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==
@@ -5574,9 +5693,9 @@ prelude-ls@~1.1.2:
integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==
prettier@^2.1.1, prettier@^2.1.2:
- version "2.7.1"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64"
- integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==
+ version "2.8.8"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
+ integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
pretty-format@^26.0.0, pretty-format@^26.6.2:
version "26.6.2"
@@ -5621,9 +5740,9 @@ psl@^1.1.33:
integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
punycode@^2.1.0, punycode@^2.1.1:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
- integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
+ integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
q@^1.5.1:
version "1.5.1"
@@ -5631,9 +5750,9 @@ q@^1.5.1:
integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
qs@^6.10.1:
- version "6.11.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
- integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
+ version "6.11.1"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.1.tgz#6c29dff97f0c0060765911ba65cbc9764186109f"
+ integrity sha512-0wsrzgTz/kAVIeuxSjnpGC56rzYtr6JT/2BwEvMaPhFIoYa1aGO8LbzuU1R0uUYQkLpWBTOj0l/CLAJB64J6nQ==
dependencies:
side-channel "^1.0.4"
@@ -5694,18 +5813,18 @@ read-pkg@^5.2.0:
type-fest "^0.6.0"
readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.0.2, readable-stream@^3.4.0:
- version "3.6.0"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
- integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+ integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@~2.3.6:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
- integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
+ integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
dependencies:
core-util-is "~1.0.0"
inherits "~2.0.3"
@@ -5745,48 +5864,43 @@ regenerate@^1.4.2:
resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
-regenerator-runtime@^0.13.10:
- version "0.13.10"
- resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.10.tgz#ed07b19616bcbec5da6274ebc75ae95634bfc2ee"
- integrity sha512-KepLsg4dU12hryUO7bp/axHAKvwGOCV0sGloQtpagJ12ai+ojVDqkeGSiRX1zlq+kjIMZ1t7gpze+26QqtdGqw==
+regenerator-runtime@^0.13.11:
+ version "0.13.11"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
+ integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
-regenerator-transform@^0.15.0:
- version "0.15.0"
- resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537"
- integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==
+regenerator-transform@^0.15.1:
+ version "0.15.1"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56"
+ integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==
dependencies:
"@babel/runtime" "^7.8.4"
regexp.prototype.flags@^1.4.3:
- version "1.4.3"
- resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
- integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb"
+ integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.3"
- functions-have-names "^1.2.2"
+ define-properties "^1.2.0"
+ functions-have-names "^1.2.3"
regexpp@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
-regexpu-core@^5.1.0:
- version "5.2.1"
- resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.1.tgz#a69c26f324c1e962e9ffd0b88b055caba8089139"
- integrity sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==
+regexpu-core@^5.3.1:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b"
+ integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==
dependencies:
+ "@babel/regjsgen" "^0.8.0"
regenerate "^1.4.2"
regenerate-unicode-properties "^10.1.0"
- regjsgen "^0.7.1"
regjsparser "^0.9.1"
unicode-match-property-ecmascript "^2.0.0"
- unicode-match-property-value-ecmascript "^2.0.0"
-
-regjsgen@^0.7.1:
- version "0.7.1"
- resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6"
- integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==
+ unicode-match-property-value-ecmascript "^2.1.0"
regjsparser@^0.9.1:
version "0.9.1"
@@ -5843,16 +5957,16 @@ resolve-global@^1.0.0:
global-dirs "^0.1.1"
resolve.exports@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
- integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999"
+ integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==
-resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.0:
- version "1.22.1"
- resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
- integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
+resolve@^1.10.0, resolve@^1.14.2, resolve@^1.20.0, resolve@^1.22.1:
+ version "1.22.2"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
+ integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
dependencies:
- is-core-module "^2.9.0"
+ is-core-module "^2.11.0"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
@@ -5889,9 +6003,9 @@ run-parallel@^1.1.9:
queue-microtask "^1.2.2"
rxjs@^7.5.5:
- version "7.5.7"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39"
- integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==
+ version "7.8.1"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
+ integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==
dependencies:
tslib "^2.1.0"
@@ -5937,9 +6051,9 @@ scrypt-js@3.0.1:
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
semver@7.x, semver@^7.1.1, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
- version "7.3.8"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798"
- integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==
+ version "7.5.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.0.tgz#ed8c5dc8efb6c629c88b23d41dc9bf40c1d96cd0"
+ integrity sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==
dependencies:
lru-cache "^6.0.0"
@@ -5973,9 +6087,9 @@ shebang-regex@^3.0.0:
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
shell-quote@^1.6.1:
- version "1.7.4"
- resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8"
- integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw==
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680"
+ integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==
shiki@^0.10.1:
version "0.10.1"
@@ -6038,9 +6152,9 @@ source-map@^0.7.3:
integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
spdx-correct@^3.0.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
- integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c"
+ integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==
dependencies:
spdx-expression-parse "^3.0.0"
spdx-license-ids "^3.0.0"
@@ -6059,9 +6173,9 @@ spdx-expression-parse@^3.0.0:
spdx-license-ids "^3.0.0"
spdx-license-ids@^3.0.0:
- version "3.0.12"
- resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz#69077835abe2710b65f03969898b6637b505a779"
- integrity sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==
+ version "3.0.13"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz#7189a474c46f8d47c7b0da4b987bb45e908bd2d5"
+ integrity sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==
split2@^3.0.0:
version "3.2.2"
@@ -6140,7 +6254,16 @@ string.prototype.padend@^3.0.0:
define-properties "^1.1.4"
es-abstract "^1.20.4"
-string.prototype.trimend@^1.0.5:
+string.prototype.trim@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533"
+ integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
+string.prototype.trimend@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533"
integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==
@@ -6149,7 +6272,7 @@ string.prototype.trimend@^1.0.5:
define-properties "^1.1.4"
es-abstract "^1.20.4"
-string.prototype.trimstart@^1.0.5:
+string.prototype.trimstart@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4"
integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==
@@ -6330,9 +6453,9 @@ text-table@^0.2.0:
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
throat@^6.0.1:
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375"
- integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.2.tgz#51a3fbb5e11ae72e2cf74861ed5c8020f89f29fe"
+ integrity sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==
through2@^2.0.0:
version "2.0.5"
@@ -6416,10 +6539,11 @@ trim-repeated@^1.0.0:
escape-string-regexp "^1.0.2"
ts-command-line-args@^2.2.0:
- version "2.3.1"
- resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.3.1.tgz#b6188e42efc6cf7a8898e438a873fbb15505ddd6"
- integrity sha512-FR3y7pLl/fuUNSmnPhfLArGqRrpojQgIEEOVzYx9DhTmfIN7C9RWSfpkJEF4J+Gk7aVx5pak8I7vWZsaN4N84g==
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/ts-command-line-args/-/ts-command-line-args-2.5.0.tgz#7eeed3a6937b2612ea08a0794cf9d43fbbea89c4"
+ integrity sha512-Ff7Xt04WWCjj/cmPO9eWTJX3qpBZWuPWyQYG1vnxJao+alWWYjwJBc5aYz3h5p5dE08A6AnpkgiCtP/0KXXBYw==
dependencies:
+ "@morgan-stanley/ts-mocking-bird" "^0.6.2"
chalk "^4.1.0"
command-line-args "^5.1.1"
command-line-usage "^6.1.0"
@@ -6464,20 +6588,20 @@ ts-node@^10.8.1:
yn "3.1.1"
ts-unused-exports@^8.0.0:
- version "8.0.0"
- resolved "https://registry.yarnpkg.com/ts-unused-exports/-/ts-unused-exports-8.0.0.tgz#6dd15ff26286e0b7e5663cda3b98c77ea6f3ffe7"
- integrity sha512-gylHFyJqC80PSb4zy35KTckykEW1vmKjnOHjBeX9iKBo4b/SzqQIcXXbYSuif4YMgNm6ewFF62VM1C9z0bGZPw==
+ version "8.0.5"
+ resolved "https://registry.yarnpkg.com/ts-unused-exports/-/ts-unused-exports-8.0.5.tgz#43b1ac25822ec9445b5fc3e57862c0d1f23471cb"
+ integrity sha512-ewEHxTtQsYQFQCI12CnMx8D0xxn1/Uui1Wr5jbiX4me+4LlSiOGvt4mGz0hxtIC3eElVaLrKEPbeT3TPrm4JvA==
dependencies:
chalk "^4.0.0"
tsconfig-paths "^3.9.0"
tsconfig-paths@^3.14.1, tsconfig-paths@^3.9.0:
- version "3.14.1"
- resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a"
- integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==
+ version "3.14.2"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088"
+ integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==
dependencies:
"@types/json5" "^0.0.29"
- json5 "^1.0.1"
+ json5 "^1.0.2"
minimist "^1.2.6"
strip-bom "^3.0.0"
@@ -6487,9 +6611,9 @@ tslib@^1.8.1:
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.1.0:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e"
- integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
+ integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
tsutils@^3.21.0:
version "3.21.0"
@@ -6563,6 +6687,15 @@ typechain@^7.0.0:
ts-command-line-args "^2.2.0"
ts-essentials "^7.0.1"
+typed-array-length@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb"
+ integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==
+ dependencies:
+ call-bind "^1.0.2"
+ for-each "^0.3.3"
+ is-typed-array "^1.1.9"
+
typedarray-to-buffer@^3.1.5:
version "3.1.5"
resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
@@ -6591,15 +6724,15 @@ typedoc@^0.22.11:
minimatch "^5.1.0"
shiki "^0.10.1"
-typescript@^4.6.4:
- version "4.8.4"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6"
- integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==
+"typescript@^4.6.4 || ^5.0.0":
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b"
+ integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==
typescript@^4.7.0:
- version "4.9.3"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.3.tgz#3aea307c1746b8c384435d8ac36b8a2e580d85db"
- integrity sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==
+ version "4.9.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
+ integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
typical@^4.0.0:
version "4.0.0"
@@ -6639,10 +6772,10 @@ unicode-match-property-ecmascript@^2.0.0:
unicode-canonical-property-names-ecmascript "^2.0.0"
unicode-property-aliases-ecmascript "^2.0.0"
-unicode-match-property-value-ecmascript@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714"
- integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==
+unicode-match-property-value-ecmascript@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0"
+ integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==
unicode-property-aliases-ecmascript@^2.0.0:
version "2.1.0"
@@ -6664,10 +6797,10 @@ universalify@^2.0.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
-update-browserslist-db@^1.0.9:
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3"
- integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==
+update-browserslist-db@^1.0.10:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940"
+ integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==
dependencies:
escalade "^3.1.1"
picocolors "^1.0.0"
@@ -6697,6 +6830,11 @@ uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
+uuid@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
+ integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
+
v8-compile-cache-lib@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
@@ -6725,9 +6863,9 @@ validate-npm-package-license@^3.0.1:
spdx-expression-parse "^3.0.0"
vscode-oniguruma@^1.6.1:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz#aeb9771a2f1dbfc9083c8a7fdd9cccaa3f386607"
- integrity sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA==
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz#439bfad8fe71abd7798338d1cd3dc53a8beea94b"
+ integrity sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==
vscode-textmate@5.2.0:
version "5.2.0"
@@ -6804,6 +6942,18 @@ which-boxed-primitive@^1.0.2:
is-string "^1.0.5"
is-symbol "^1.0.3"
+which-typed-array@^1.1.9:
+ version "1.1.9"
+ resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6"
+ integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==
+ dependencies:
+ available-typed-arrays "^1.0.5"
+ call-bind "^1.0.2"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ has-tostringtag "^1.0.0"
+ is-typed-array "^1.1.10"
+
which@^1.2.14, which@^1.2.9:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
@@ -6890,16 +7040,16 @@ y18n@^5.0.5:
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+yallist@^3.0.2:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
+ integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
-yaml@^1.10.0:
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
- integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
-
yargs-parser@20.x, yargs-parser@^20.2.2, yargs-parser@^20.2.3:
version "20.2.9"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
From 58755d9edecae1b048ba6a748342db83e34d573a Mon Sep 17 00:00:00 2001
From: piotr-roslaniec <39299780+piotr-roslaniec@users.noreply.github.com>
Date: Thu, 4 May 2023 12:15:04 +0100
Subject: [PATCH 07/98] Bump `nucypher-core` version (#193)
feat!: bump nucypher-core to 0.7.0
---
README.md | 7 ++--
package.json | 4 +-
src/characters/bob.ts | 4 +-
src/characters/porter.ts | 10 +++--
src/characters/universal-bob.ts | 13 +++---
src/keyring.ts | 2 +-
src/policies/policy.ts | 2 +-
src/sdk/strategy.ts | 22 +++++-----
test/acceptance/alice-grants.test.ts | 25 +++++++++---
test/acceptance/delay-enact.test.ts | 6 +--
test/docs/cbd.test.ts | 8 ++--
test/integration/conditions.test.ts | 2 +-
test/integration/enrico.test.ts | 4 +-
test/integration/pre.test.ts | 4 +-
test/unit/cohort.test.ts | 10 ++---
test/unit/strategy.test.ts | 57 +++++++++++++-------------
test/unit/testVariables.ts | 60 ++++++++++++++++++++++++----
test/utils.ts | 27 +++++++------
yarn.lock | 8 ++--
19 files changed, 173 insertions(+), 102 deletions(-)
diff --git a/README.md b/README.md
index 5cd089265..c85ae1b19 100644
--- a/README.md
+++ b/README.md
@@ -7,9 +7,9 @@ Full documentation can be found [here](https://docs.threshold.network/app-develo
> **Warning**
>
> `nucypher-ts` is under [active development](https://github.com/nucypher/nucypher-ts/pulls):
->
-> - SDK does not support policy revocation.
-> - We expect breaking changes.
+>
+> - SDK does not support policy revocation.
+> - We expect breaking changes.
## Installation
@@ -26,6 +26,7 @@ To learn more, follow the tutorial at Threshold Network's [docs](https://docs.th
See [`nucypher-ts/examples`](https://github.com/nucypher/nucypher-ts/tree/main/examples) to find out how to integrate `nucypher-ts` into your favorite web framework.
We also provide two code samples of TAC applications:
+
- [nucypher/tdec-sandbox](https://github.com/nucypher/tdec-sandbox)
- [nucypher/tdec-nft-example](https://github.com/nucypher/tdec-nft-example)
diff --git a/package.json b/package.json
index 7bcc725b3..23a48e6e2 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
"test:lint": "eslint src test --ext .ts",
"test:exports": "ts-unused-exports tsconfig.json --ignoreFiles src/index.ts",
"test:prettier": "prettier \"src/**/*.ts\" \"test/**/*.ts\" --list-different",
- "test:unit": "jest",
+ "test:unit": "jest --detectOpenHandles --forceExit --runInBand",
"watch:build": "tsc -p tsconfig.json -w",
"watch:test": "jest --watch",
"cov": "run-s build test:unit && open-cli coverage/index.html",
@@ -52,7 +52,7 @@
"prebuild": "yarn typechain"
},
"dependencies": {
- "@nucypher/nucypher-core": "0.4.0",
+ "@nucypher/nucypher-core": "^0.7.0",
"axios": "^0.21.1",
"ethers": "^5.4.1",
"joi": "^17.7.0",
diff --git a/src/characters/bob.ts b/src/characters/bob.ts
index 5d4c67101..1ee8606af 100644
--- a/src/characters/bob.ts
+++ b/src/characters/bob.ts
@@ -27,11 +27,11 @@ export class RemoteBob {
const dk =
decryptingKey instanceof PublicKey
? decryptingKey
- : PublicKey.fromBytes(decryptingKey);
+ : PublicKey.fromCompressedBytes(decryptingKey);
const vk =
verifyingKey instanceof PublicKey
? verifyingKey
- : PublicKey.fromBytes(verifyingKey);
+ : PublicKey.fromCompressedBytes(verifyingKey);
return new RemoteBob(dk, vk);
}
}
diff --git a/src/characters/porter.ts b/src/characters/porter.ts
index 7834ab491..ee0df9a40 100644
--- a/src/characters/porter.ts
+++ b/src/characters/porter.ts
@@ -93,7 +93,9 @@ export class Porter {
return resp.data.result.ursulas.map((u: UrsulaResponse) => ({
checksumAddress: u.checksum_address,
uri: u.uri,
- encryptingKey: PublicKey.fromBytes(fromHexString(u.encrypting_key)),
+ encryptingKey: PublicKey.fromCompressedBytes(
+ fromHexString(u.encrypting_key)
+ ),
}));
}
@@ -111,9 +113,9 @@ export class Porter {
const data: PostRetrieveCFragsRequest = {
treasure_map: toBase64(treasureMap.toBytes()),
retrieval_kits: retrievalKits.map((rk) => toBase64(rk.toBytes())),
- alice_verifying_key: toHexString(aliceVerifyingKey.toBytes()),
- bob_encrypting_key: toHexString(bobEncryptingKey.toBytes()),
- bob_verifying_key: toHexString(bobVerifyingKey.toBytes()),
+ alice_verifying_key: toHexString(aliceVerifyingKey.toCompressedBytes()),
+ bob_encrypting_key: toHexString(bobEncryptingKey.toCompressedBytes()),
+ bob_verifying_key: toHexString(bobVerifyingKey.toCompressedBytes()),
context,
};
const resp: AxiosResponse = await axios.post(
diff --git a/src/characters/universal-bob.ts b/src/characters/universal-bob.ts
index be8b6afc6..3bdbb95d7 100644
--- a/src/characters/universal-bob.ts
+++ b/src/characters/universal-bob.ts
@@ -140,10 +140,11 @@ export class tDecDecrypter {
public toObj(): decrypterJSON {
return {
porterUri: this.porter.porterUrl.toString(),
- policyEncryptingKeyBytes: this.policyEncryptingKey.toBytes(),
+ policyEncryptingKeyBytes: this.policyEncryptingKey.toCompressedBytes(),
encryptedTreasureMapBytes: this.encryptedTreasureMap.toBytes(),
- publisherVerifyingKeyBytes: this.publisherVerifyingKey.toBytes(),
- bobSecretKeyBytes: this.keyring.secretKey.toSecretBytes(),
+ publisherVerifyingKeyBytes:
+ this.publisherVerifyingKey.toCompressedBytes(),
+ bobSecretKeyBytes: this.keyring.secretKey.toBEBytes(),
};
}
@@ -160,10 +161,10 @@ export class tDecDecrypter {
}: decrypterJSON) {
return new tDecDecrypter(
porterUri,
- PublicKey.fromBytes(policyEncryptingKeyBytes),
+ PublicKey.fromCompressedBytes(policyEncryptingKeyBytes),
EncryptedTreasureMap.fromBytes(encryptedTreasureMapBytes),
- PublicKey.fromBytes(publisherVerifyingKeyBytes),
- SecretKey.fromBytes(bobSecretKeyBytes)
+ PublicKey.fromCompressedBytes(publisherVerifyingKeyBytes),
+ SecretKey.fromBEBytes(bobSecretKeyBytes)
);
}
diff --git a/src/keyring.ts b/src/keyring.ts
index 4e0f06b99..4b769b95e 100644
--- a/src/keyring.ts
+++ b/src/keyring.ts
@@ -55,7 +55,7 @@ export class Keyring {
private getSecretKeyFromLabel(label: string): SecretKey {
return SecretKeyFactory.fromSecureRandomness(
- this.secretKey.toSecretBytes()
+ this.secretKey.toBEBytes()
).makeKey(toBytes(label));
}
diff --git a/src/policies/policy.ts b/src/policies/policy.ts
index 54d95719e..dbb23eccb 100644
--- a/src/policies/policy.ts
+++ b/src/policies/policy.ts
@@ -131,7 +131,7 @@ export class BlockchainPolicy {
this.delegatingKey,
encryptedTreasureMap,
// revocationKit,
- this.publisher.verifyingKey.toBytes(),
+ this.publisher.verifyingKey.toCompressedBytes(),
this.shares,
this.startDate,
this.endDate
diff --git a/src/sdk/strategy.ts b/src/sdk/strategy.ts
index 15190f8b8..490e44d57 100644
--- a/src/sdk/strategy.ts
+++ b/src/sdk/strategy.ts
@@ -136,8 +136,8 @@ export class Strategy {
}: StrategyJSON) {
return new Strategy(
Cohort.fromObj(cohort),
- SecretKey.fromBytes(aliceSecretKeyBytes),
- SecretKey.fromBytes(bobSecretKeyBytes),
+ SecretKey.fromBEBytes(aliceSecretKeyBytes),
+ SecretKey.fromBEBytes(bobSecretKeyBytes),
startDate,
endDate,
conditionSet
@@ -147,8 +147,8 @@ export class Strategy {
public toObj(): StrategyJSON {
return {
cohort: this.cohort.toObj(),
- aliceSecretKeyBytes: this.aliceSecretKey.toSecretBytes(),
- bobSecretKeyBytes: this.bobSecretKey.toSecretBytes(),
+ aliceSecretKeyBytes: this.aliceSecretKey.toBEBytes(),
+ bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
conditionSet: this.conditionSet,
startDate: this.startDate,
endDate: this.endDate,
@@ -183,23 +183,25 @@ export class DeployedStrategy {
conditionSet,
}: DeployedStrategyJSON) {
const id = HRAC.fromBytes(policy.id);
- const policyKey = PublicKey.fromBytes(policy.policyKey);
+ const policyKey = PublicKey.fromCompressedBytes(policy.policyKey);
const encryptedTreasureMap = EncryptedTreasureMap.fromBytes(
policy.encryptedTreasureMap
);
- const aliceVerifyingKey = PublicKey.fromBytes(policy.aliceVerifyingKey);
+ const aliceVerifyingKey = PublicKey.fromCompressedBytes(
+ policy.aliceVerifyingKey
+ );
const newPolicy = {
id,
label: policy.label,
policyKey,
encryptedTreasureMap,
- aliceVerifyingKey: aliceVerifyingKey.toBytes(),
+ aliceVerifyingKey: aliceVerifyingKey.toCompressedBytes(),
size: policy.size,
startTimestamp: policy.startTimestamp,
endTimestamp: policy.endTimestamp,
txHash: policy.txHash,
};
- const bobSecretKey = SecretKey.fromBytes(bobSecretKeyBytes);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
const label = newPolicy.label;
const cohort = Cohort.fromObj(cohortConfig);
const encrypter = new Enrico(newPolicy.policyKey, undefined, conditionSet);
@@ -226,13 +228,13 @@ export class DeployedStrategy {
const policy = {
...this.policy,
id: this.policy.id.toBytes(),
- policyKey: this.policy.policyKey.toBytes(),
+ policyKey: this.policy.policyKey.toCompressedBytes(),
encryptedTreasureMap: this.policy.encryptedTreasureMap.toBytes(),
};
return {
policy,
cohortConfig: this.cohort.toObj(),
- bobSecretKeyBytes: this.bobSecretKey.toSecretBytes(),
+ bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
conditionSet: this.conditionSet,
};
}
diff --git a/test/acceptance/alice-grants.test.ts b/test/acceptance/alice-grants.test.ts
index 3e1f661aa..f4414e2bb 100644
--- a/test/acceptance/alice-grants.test.ts
+++ b/test/acceptance/alice-grants.test.ts
@@ -12,6 +12,7 @@ import { toBytes } from '../../src/utils';
import {
bytesEqual,
fromBytes,
+ makeTestUrsulas,
mockAlice,
mockBob,
mockEncryptTreasureMap,
@@ -21,7 +22,6 @@ import {
mockPublishToBlockchain,
mockRemoteBob,
mockRetrieveCFragsRequest,
- mockUrsulas,
reencryptKFrags,
} from '../utils';
@@ -31,7 +31,7 @@ describe('story: alice shares message with bob through policy', () => {
const shares = 3;
const startDate = new Date();
const endDate = new Date(Date.now() + 60 * 1000);
- const mockedUrsulas = mockUrsulas().slice(0, shares);
+ const mockedUrsulas = makeTestUrsulas().slice(0, shares);
// Intermediate variables used for mocking
let encryptedTreasureMap: EncryptedTreasureMap;
@@ -64,7 +64,9 @@ describe('story: alice shares message with bob through policy', () => {
};
policy = await alice.grant(policyParams);
- expect(policy.aliceVerifyingKey).toEqual(alice.verifyingKey.toBytes());
+ expect(policy.aliceVerifyingKey).toEqual(
+ alice.verifyingKey.toCompressedBytes()
+ );
expect(policy.label).toBe(label);
expect(getUrsulasSpy).toHaveBeenCalled();
expect(generateKFragsSpy).toHaveBeenCalled();
@@ -121,12 +123,23 @@ describe('story: alice shares message with bob through policy', () => {
bobVerifyingKey_,
] = retrieveCFragsSpy.mock.calls[0];
expect(
- bytesEqual(aliceVerifyingKey_.toBytes(), aliceVerifyingKey.toBytes())
+ bytesEqual(
+ aliceVerifyingKey_.toCompressedBytes(),
+ aliceVerifyingKey.toCompressedBytes()
+ )
+ );
+ expect(
+ bytesEqual(
+ bobEncryptingKey_.toCompressedBytes(),
+ bob.decryptingKey.toCompressedBytes()
+ )
);
expect(
- bytesEqual(bobEncryptingKey_.toBytes(), bob.decryptingKey.toBytes())
+ bytesEqual(
+ bobVerifyingKey_.toCompressedBytes(),
+ bob.verifyingKey.toCompressedBytes()
+ )
);
- expect(bytesEqual(bobVerifyingKey_.toBytes(), bob.verifyingKey.toBytes()));
const { verifiedCFrags } = reencryptKFrags(
verifiedKFrags,
diff --git a/test/acceptance/delay-enact.test.ts b/test/acceptance/delay-enact.test.ts
index 6ca4cc623..151719f6f 100644
--- a/test/acceptance/delay-enact.test.ts
+++ b/test/acceptance/delay-enact.test.ts
@@ -1,11 +1,11 @@
import {
+ makeTestUrsulas,
mockAlice,
mockEncryptTreasureMap,
mockGenerateKFrags,
mockGetUrsulas,
mockPublishToBlockchain,
mockRemoteBob,
- mockUrsulas,
} from '../utils';
describe('story: alice1 creates a policy but alice2 enacts it', () => {
@@ -13,7 +13,7 @@ describe('story: alice1 creates a policy but alice2 enacts it', () => {
const shares = 3;
const startDate = new Date();
const endDate = new Date(Date.now() + 60 * 1000); // 60s later
- const mockedUrsulas = mockUrsulas().slice(0, shares);
+ const mockedUrsulas = makeTestUrsulas().slice(0, shares);
const label = 'fake-data-label';
it('alice generates a new policy', async () => {
@@ -38,7 +38,7 @@ describe('story: alice1 creates a policy but alice2 enacts it', () => {
policyParams
);
expect(preEnactedPolicy.aliceVerifyingKey).toEqual(
- alice1.verifyingKey.toBytes()
+ alice1.verifyingKey.toCompressedBytes()
);
expect(preEnactedPolicy.label).toBe(label);
diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts
index 650ad1f2f..956448355 100644
--- a/test/docs/cbd.test.ts
+++ b/test/docs/cbd.test.ts
@@ -11,6 +11,7 @@ import {
import { Ursula } from '../../src/characters/porter';
import { toBytes } from '../../src/utils';
import {
+ makeTestUrsulas,
mockDetectEthereumProvider,
mockEncryptTreasureMap,
mockGenerateKFrags,
@@ -18,7 +19,6 @@ import {
mockMakeTreasureMap,
mockPublishToBlockchain,
mockRetrieveCFragsRequest,
- mockUrsulas,
mockWeb3Provider,
} from '../utils';
@@ -42,7 +42,7 @@ describe('Get Started (CBD PoC)', () => {
it('can run the get started example', async () => {
const detectEthereumProvider = mockDetectEthereumProvider();
- const mockedUrsulas = mockUrsulas();
+ const mockedUrsulas = makeTestUrsulas();
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -52,7 +52,7 @@ describe('Get Started (CBD PoC)', () => {
jest
.spyOn(providers, 'Web3Provider')
.mockImplementation(() =>
- mockWeb3Provider(SecretKey.random().toSecretBytes())
+ mockWeb3Provider(SecretKey.random().toBEBytes())
);
//
@@ -126,7 +126,7 @@ describe('Get Started (CBD PoC)', () => {
// End of the code example
//
- const expectedAddresses = mockUrsulas().map((u) => u.checksumAddress);
+ const expectedAddresses = makeTestUrsulas().map((u) => u.checksumAddress);
const condObj = conditions.conditions[0].toObj();
expect(newCohort.ursulaAddresses).toEqual(expectedAddresses);
expect(condObj.parameters).toEqual([5954]);
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index 5fe41aa84..373a2d54e 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -239,7 +239,7 @@ describe('produce context parameters from conditions', () => {
describe('condition context', () => {
it('should serialize to JSON with context params', async () => {
- const web3Provider = mockWeb3Provider(SecretKey.random().toSecretBytes());
+ const web3Provider = mockWeb3Provider(SecretKey.random().toBEBytes());
const rpcCondition = new Conditions.RpcCondition({
chain: 5,
diff --git a/test/integration/enrico.test.ts b/test/integration/enrico.test.ts
index f3281b0ad..fb57894c4 100644
--- a/test/integration/enrico.test.ts
+++ b/test/integration/enrico.test.ts
@@ -51,7 +51,9 @@ describe('enrico', () => {
threshold,
shares
);
- expect(delegatingKey.toBytes()).toEqual(policyEncryptingKey.toBytes());
+ expect(delegatingKey.toCompressedBytes()).toEqual(
+ policyEncryptingKey.toCompressedBytes()
+ );
// Bob can decrypt re-encrypted ciphertext
const { verifiedCFrags } = reencryptKFrags(
diff --git a/test/integration/pre.test.ts b/test/integration/pre.test.ts
index c896c7b6c..b5bf3c311 100644
--- a/test/integration/pre.test.ts
+++ b/test/integration/pre.test.ts
@@ -10,13 +10,13 @@ import {
} from '../../src';
import { RetrievalResult } from '../../src/kits/retrieval';
import { toBytes, zip } from '../../src/utils';
-import { mockAlice, mockBob, mockUrsulas, reencryptKFrags } from '../utils';
+import { makeTestUrsulas, mockAlice, mockBob, reencryptKFrags } from '../utils';
describe('proxy reencryption', () => {
const plaintext = toBytes('plaintext-message');
const threshold = 2;
const shares = 3;
- const ursulas = mockUrsulas().slice(0, shares);
+ const ursulas = makeTestUrsulas().slice(0, shares);
const label = 'fake-data-label';
const alice = mockAlice();
const bob = mockBob();
diff --git a/test/unit/cohort.test.ts b/test/unit/cohort.test.ts
index 54ed84457..7cfd66eea 100644
--- a/test/unit/cohort.test.ts
+++ b/test/unit/cohort.test.ts
@@ -1,9 +1,9 @@
-import { Cohort } from '../../src/sdk/cohort';
-import { mockGetUrsulas, mockUrsulas } from '../utils';
+import { Cohort } from '../../src';
+import { makeTestUrsulas, mockGetUrsulas } from '../utils';
describe('Cohort', () => {
it('can create Cohort from configuration', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const config = {
@@ -23,7 +23,7 @@ describe('Cohort', () => {
});
it('can export to JSON', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const config = {
threshold: 2,
@@ -39,7 +39,7 @@ describe('Cohort', () => {
});
it('can import from JSON', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const configJSON =
diff --git a/test/unit/strategy.test.ts b/test/unit/strategy.test.ts
index be450cc69..38ada25b3 100644
--- a/test/unit/strategy.test.ts
+++ b/test/unit/strategy.test.ts
@@ -15,13 +15,13 @@ import {
import { Ursula } from '../../src/characters/porter';
import { fromBase64, toBytes } from '../../src/utils';
import {
+ makeTestUrsulas,
mockEncryptTreasureMap,
mockGenerateKFrags,
mockGetUrsulas,
mockMakeTreasureMap,
mockPublishToBlockchain,
mockRetrieveCFragsRequest,
- mockUrsulas,
mockWeb3Provider,
} from '../utils';
@@ -40,17 +40,17 @@ describe('Strategy', () => {
shares: 3,
porterUri: 'https://_this.should.crash',
};
- const aliceSecretKey = SecretKey.fromBytes(aliceSecretKeyBytes);
- const bobSecretKey = SecretKey.fromBytes(bobSecretKeyBytes);
- const aliceProvider = mockWeb3Provider(aliceSecretKey.toSecretBytes());
+ const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
+ const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
Date.now = jest.fn(() => 1487076708000);
afterEach(() => {
- jest.clearAllMocks();
+ jest.restoreAllMocks();
});
it('can create Strategy from configuration', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const testCohort = await Cohort.create(cohortConfig);
@@ -61,26 +61,29 @@ describe('Strategy', () => {
bobSecretKey
);
- const expectedUrsulas = [
- '0x5cf1703a1c99a4b42eb056535840e93118177232',
- '0x7fff551249d223f723557a96a0e1a469c79cc934',
- '0x9c7c824239d3159327024459ad69bb215859bd25',
- ];
+ const expectedUrsulas = mockedUrsulas.map(
+ (ursula) => ursula.checksumAddress
+ );
expect(getUrsulasSpy).toHaveBeenCalled();
expect(testStrategy.cohort.ursulaAddresses).toEqual(expectedUrsulas);
});
it('can export to JSON', async () => {
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
+ const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const testCohort = await Cohort.create(cohortConfig);
const testStrategy = Strategy.create(
testCohort,
undefined,
aliceSecretKey,
- bobSecretKey
+ bobSecretKey,
+ new Date('2017-02-14T12:51:48.000Z'),
+ new Date('2123-03-16T12:51:48.000Z')
);
const configJSON = testStrategy.toJSON();
expect(configJSON).toEqual(strategyJSON);
+ expect(getUrsulasSpy).toHaveBeenCalled();
});
it('can import from JSON', async () => {
@@ -94,7 +97,7 @@ describe('Strategy', () => {
});
it('can deploy and return DeployedStrategy', async () => {
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -120,16 +123,16 @@ describe('Deployed Strategy', () => {
shares: 3,
porterUri: 'https://_this.should.crash',
};
- const aliceSecretKey = SecretKey.fromBytes(aliceSecretKeyBytes);
- const bobSecretKey = SecretKey.fromBytes(bobSecretKeyBytes);
+ const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
afterEach(() => {
- jest.clearAllMocks();
+ jest.restoreAllMocks();
});
it('can export to JSON', async () => {
- const aliceProvider = mockWeb3Provider(aliceSecretKey.toSecretBytes());
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -143,7 +146,9 @@ describe('Deployed Strategy', () => {
testCohort,
undefined,
aliceSecretKey,
- bobSecretKey
+ bobSecretKey,
+ new Date('2017-02-14T12:51:48.000Z'),
+ new Date('2123-03-16T12:51:48.000Z')
);
const testDeployed = await testStrategy.deploy('test', aliceProvider);
expect(getUrsulasSpy).toHaveBeenCalled();
@@ -163,9 +168,9 @@ describe('Deployed Strategy', () => {
});
it('can encrypt and decrypt', async () => {
- const aliceProvider = mockWeb3Provider(aliceSecretKey.toSecretBytes());
- const bobProvider = mockWeb3Provider(bobSecretKey.toSecretBytes());
- const mockedUrsulas = mockUrsulas().slice(0, 3);
+ const aliceProvider = mockWeb3Provider(aliceSecretKey.toBEBytes());
+ const bobProvider = mockWeb3Provider(bobSecretKey.toBEBytes());
+ const mockedUrsulas = makeTestUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
@@ -195,11 +200,10 @@ describe('Deployed Strategy', () => {
parameters: [3591],
chain: 5,
});
-
const plaintext = 'this is a secret';
- const conditions = new ConditionSet([ownsNFT]);
- encrypter.conditions = conditions;
+ encrypter.conditions = new ConditionSet([ownsNFT]);
const encryptedMessageKit = encrypter.encryptMessage(plaintext);
+
// Setup mocks for `retrieveAndDecrypt`
const getUrsulasSpy2 = mockGetUrsulas(mockedUrsulas);
const ursulaAddresses = (
@@ -227,8 +231,7 @@ describe('tDecDecrypter', () => {
const importedStrategy = DeployedStrategy.fromJSON(deployedStrategyJSON);
it('can export to JSON', () => {
- const decrypter = importedStrategy.decrypter;
- const configJSON = decrypter.toJSON();
+ const configJSON = importedStrategy.decrypter.toJSON();
expect(configJSON).toEqual(decrypterJSON);
});
diff --git a/test/unit/testVariables.ts b/test/unit/testVariables.ts
index 643c853c9..34c1cc099 100644
--- a/test/unit/testVariables.ts
+++ b/test/unit/testVariables.ts
@@ -1,12 +1,48 @@
-export const strategyJSON =
- '{"cohort":{"ursulaAddresses":["0x5cf1703a1c99a4b42eb056535840e93118177232","0x7fff551249d223f723557a96a0e1a469c79cc934","0x9c7c824239d3159327024459ad69bb215859bd25"],"threshold":2,"shares":3,"porterUri":"https://_this.should.crash"},"aliceSecretKeyBytes":"base64:N1K+vcukPJQkVi57P5jXca5W9CwX48VEBVV0H9CYWDU=","bobSecretKeyBytes":"base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=","startDate":"2017-02-14T12:51:48.000Z","endDate":"2017-03-16T12:51:48.000Z"}';
+export const strategyJSON = JSON.stringify({
+ cohort: {
+ ursulaAddresses: [
+ '0x5cf1703a1c99a4b42eb056535840e93118177232',
+ '0x7fff551249d223f723557a96a0e1a469c79cc934',
+ '0x9c7c824239d3159327024459ad69bb215859bd25',
+ ],
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ },
+ aliceSecretKeyBytes: 'base64:N1K+vcukPJQkVi57P5jXca5W9CwX48VEBVV0H9CYWDU=',
+ bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
+ startDate: '2017-02-14T12:51:48.000Z',
+ endDate: '2123-03-16T12:51:48.000Z',
+});
export const encryptedTreasureMapBase64 =
- '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';
-
-export const deployedStrategyJSON =
- '{"policy":{"id":"base64:tKuR/HipMeU4trCdytbZCQ==","label":"test","policyKey":"base64:A/u/2+G8Hn0UPwRZqVfa41XiT/6W2+98dotTob7xKg5C","encryptedTreasureMap":"base64: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","aliceVerifyingKey":"base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj","size":3,"startTimestamp":"2017-02-14T12:51:48.000Z","endTimestamp":"2017-03-16T12:51:48.000Z","txHash":"0x1234567890123456789012345678901234567890"},"cohortConfig":{"ursulaAddresses":["0x5cf1703a1c99a4b42eb056535840e93118177232","0x7fff551249d223f723557a96a0e1a469c79cc934","0x9c7c824239d3159327024459ad69bb215859bd25"],"threshold":2,"shares":3,"porterUri":"https://_this.should.crash"},"bobSecretKeyBytes":"base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk="}';
+ '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';
+export const deployedStrategyJSON = JSON.stringify({
+ policy: {
+ id: 'base64:tKuR/HipMeU4trCdytbZCQ==',
+ label: 'test',
+ policyKey: 'base64:A/u/2+G8Hn0UPwRZqVfa41XiT/6W2+98dotTob7xKg5C',
+ encryptedTreasureMap:
+ 'base64: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',
+ aliceVerifyingKey: 'base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj',
+ size: 3,
+ startTimestamp: '2017-02-14T12:51:48.000Z',
+ endTimestamp: '2123-03-16T12:51:48.000Z',
+ txHash: '0x1234567890123456789012345678901234567890',
+ },
+ cohortConfig: {
+ ursulaAddresses: [
+ '0x5cf1703a1c99a4b42eb056535840e93118177232',
+ '0x7fff551249d223f723557a96a0e1a469c79cc934',
+ '0x9c7c824239d3159327024459ad69bb215859bd25',
+ ],
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ },
+ bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
+});
export const aliceSecretKeyBytes = new Uint8Array([
55, 82, 190, 189, 203, 164, 60, 148, 36, 86, 46, 123, 63, 152, 215, 113, 174,
86, 244, 44, 23, 227, 197, 68, 5, 85, 116, 31, 208, 152, 88, 53,
@@ -17,5 +53,13 @@ export const bobSecretKeyBytes = new Uint8Array([
229, 2, 106, 176, 205, 33, 168, 23, 213, 233, 200, 238, 11, 193, 153,
]);
-export const decrypterJSON =
- '{"porterUri":"https://_this.should.crash/","policyEncryptingKeyBytes":"base64:A/u/2+G8Hn0UPwRZqVfa41XiT/6W2+98dotTob7xKg5C","encryptedTreasureMapBytes":"base64:RU1hcAABAACSxGIDdzg9r81RRC+kQGy0C0s8LdQXwcDf+MJtuJ9+i3Zp+bICp+WRepaHInVIh7O3hiiz0Frs4Xr7sct2nNaXHrbFLgzKHdNnmhg7EIpPWs2HUJMjwh4Ny0rKVyx2/Ilvh24t5sUGtg2tnZKEMnf1Z9E8wIEv1itZmsjjXmnlrshHxPdQ/1cJneXIU+ch+n7t+BJQkOJSfLE74++KZJ+mUnPpCh8QWssHeeGNBeB2oB9CtpmcBzDoLdJJClTVte4OmADofiQ6RJswQfGCM6Gw21rJOqm5q7/6jaR47gvMlu/A94Y3WkiUAFbaGcr4vQzeAflRsR0N9LPfKIIqHfajWNCEagp0GgoaG6DsQVeEnaL7z+meg8HeQdO+m09OFh4b8Ic0m2BtYSscrlUBlU5JWrxKtLjPuxBTIQyX8FQV6gYnLyzkAEBAOgPgjuwHsTZeFUatTDYYhA/Y2hlfdmLeYW5pZ74/+uNJBof/9QB1beCn+TfrTbVyjGADn2JU8NwhnsNdDM3XFQy6WUoHLrnTs4lYj16unC7Ir6DnI6UXj84ixjli2ge8wgHpZkmQJKrMc1HvfDlM3TWG18rvEB0fE70sSMGhhegp/cjh52C3eTUACaEkO127r1kF/NjCDtbOsk9CnD2mwGyOMdr17B5TojWINwJ0SsT9gCgnZjEuxbX45NAr+M+Nz4TwbPF8ap67mj3dbGvuokNHsBfjn8YCRAIDgP83SYnR/Y4VqqKL7uzRbfmu2ljCkTohe9rJUNhwaVYpl0PODuVZQo1jAmSBZ9/HzVNbkqGwiTAtjz5CHXW7oKl8SwXiBUHXXOu0jvi8RgOP9BZeoL48sFLiSWDIxI2XAxEEuaD16vgvvthl0mxklP7R5p7vvAfAdP/lNCy28B5r7PPsXh6MmYyyaObetm2HzcJhB3sijfXHM5iEoQ41PKXRTRxrgAw1eVAjOnNW3Ld9LJEOqB6hh/U3UYUPhrXkk4kdc7EAm4gTMbq5wmEsZQRnWIn5IsBEAMFlh3z6PvtrcuwRJkIwQSF96Ai0kE776e9pjsiuEUyZFyn4wRTfg2mxdteiC4vKTBxh2BJNVxzRONtTMgcZ0JHZpCf/ZRct2Bke8F4eWn+AmtYDQEdASHnJQtjQPe5Fl5LoePZ1uIVaKgWywz6pV4zvX4hBAZ2gK/wo8hzJNRtAaKoAr8FQxG9HUlY2htZmCtI60m2a2y8Vj3IKTa2X/2PqB/OnuZEq18FCve91TmKqghCHqteB1ON6dMl+1XK4WpTlyELbha6cni8er2w4dDO+P6e40lWzQJKUlfyYfCoB8uRDCLw82a58kG80dYGZFZAmGhqItL9RC6Ofm2TBq0F+jfdSS3DVxrJG5AldhuKbIK73ojAaLV8FVjRyT6uwo6M4JAj12krCgbvOXUaHM3jT08ZFmOI0ldmzG/I6I73LHEGm7Hey6a+K4ry5EiXA+KgLMNA8pct6HihOKBws7ckClqYOos6nAyUkABpbASdfmyat8jtUNyIXprEtZr4wvB/2E011cf9EsnIVhEovpPmvMp7IdgID0Qxs219MFFr7sJ5XjHeOINA4jb6gh5r5uQzuYtpmxv7ppi8fs/x0co8pOsgHDfy4zRGDys/Z9f/QrEB6VHms9xh7Kwpp3HLAtCcEAkCg+AsnC++6VMwWwvcLbjfE2uIYsVJJ+ciX7rSYZyDzC0IayyqNJLgS30li1xPb2u5YHMA+2vzSQGx9Zae2QSXFwDQ5Qui94RfQP//x6pqZuutXI8fqGDey50DYtPYd8J6AiKcoOPBivqSTMXj2Nb9FItbDm5DYTRM7CmQkmbYLR+/hord5AFSYauEB3zsqME3vD3mBY5OvWfPqnSpUUGe2RTF+u3mtmcfptaO9fwWSr6ckBwBMB42DuoyXVuYsdXA6WCtqCjQGqCBG0qsvOJFA3Rd2q5cy4Q+V537LlOJAkhSu/9/1WDma7JbELCSq5fCl9hOVJ96c8CfJacSVhNM4LRT71qDEf9wI2AVQrjYeMGdSXDEtidXyz1oPZpCoc8mPALPLOvgwBhLYK175NteQ9GQ+9ySMI1NWBbv/FP1jwKrFtT46FdFQHKv8xc/z29muPNPmgev3ht1tvPzrrvyCtQLdASaaHTc1FlZcMlYopgOxvz8q3MUki0wjwpVudTSaowf8Bfduj3r6TSPo11+k97P49fy3LLxOsTrvVaetD0rNIs704MI0/DmNZd0FkqyX6JzFILUCZunK9azQoJX9vr9BzsQJ2r3vmlSYNA+n9C2+YIcZqE7nHjO38XTbnfCcrZvWohBZ+Q9gDWPD7Y378w3OgIrkzNEUJhFHCahLVj41l3Y3HIMI8GM98uejNjEVZLW6NEMrjhGh+aimmvgFCAIJYXFMFe8oSfeFRQBQnvOc0y+XJl5Mbm6g5oKp","publisherVerifyingKeyBytes":"base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj","bobSecretKeyBytes":"base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk="}';
+export const decrypterJSON = JSON.stringify({
+ porterUri: 'https://_this.should.crash/',
+ policyEncryptingKeyBytes:
+ 'base64:A/u/2+G8Hn0UPwRZqVfa41XiT/6W2+98dotTob7xKg5C',
+ encryptedTreasureMapBytes:
+ 'base64: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',
+ publisherVerifyingKeyBytes:
+ 'base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj',
+ bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
+});
diff --git a/test/utils.ts b/test/utils.ts
index c27b5da7b..f4a0bac71 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -6,6 +6,7 @@ import {
Capsule,
CapsuleFrag,
EncryptedTreasureMap,
+ PublicKey,
reencrypt,
SecretKey,
VerifiedCapsuleFrag,
@@ -37,7 +38,7 @@ const mockConfig: Configuration = {
};
export const mockBob = (): Bob => {
- const secretKey = SecretKey.fromBytes(
+ const secretKey = SecretKey.fromBEBytes(
toBytes('fake-secret-key-32-bytes-bob-xxx')
);
return Bob.fromSecretKey(mockConfig, secretKey);
@@ -49,8 +50,8 @@ export const mockRemoteBob = (): RemoteBob => {
};
export const mockAlice = (aliceKey = 'fake-secret-key-32-bytes-alice-x') => {
- const secretKey = SecretKey.fromBytes(toBytes(aliceKey));
- const provider = mockWeb3Provider(secretKey.toSecretBytes());
+ const secretKey = SecretKey.fromBEBytes(toBytes(aliceKey));
+ const provider = mockWeb3Provider(secretKey.toBEBytes());
return Alice.fromSecretKey(mockConfig, secretKey, provider);
};
@@ -80,7 +81,7 @@ export const mockWeb3Provider = (
} as unknown as ethers.providers.Web3Provider;
};
-export const mockUrsulas = (): readonly Ursula[] => {
+export const makeTestUrsulas = (): readonly Ursula[] => {
return [
{
encryptingKey: SecretKey.random().publicKey(),
@@ -123,7 +124,7 @@ export const mockGetUrsulas = (ursulas: readonly Ursula[]) => {
return {
result: {
ursulas: mockUrsulas.map(({ encryptingKey, uri, checksumAddress }) => ({
- encrypting_key: toHexString(encryptingKey.toBytes()),
+ encrypting_key: toHexString(encryptingKey.toCompressedBytes()),
uri: uri,
checksum_address: checksumAddress,
})),
@@ -148,11 +149,6 @@ export const mockCFragResponse = (
verifiedKFrags: readonly VerifiedKeyFrag[],
capsule: Capsule
): readonly RetrieveCFragsResponse[] => {
- if (ursulas.length !== verifiedKFrags.length) {
- throw new Error(
- 'Number of verifiedKFrags must match the number of Ursulas'
- );
- }
const reencrypted = verifiedKFrags
.map((kFrag) => reencrypt(capsule, kFrag))
.map((cFrag) => CapsuleFrag.fromBytes(cFrag.toBytes()));
@@ -179,8 +175,15 @@ export const mockRetrieveCFragsRequestThrows = () => {
.mockRejectedValue(new Error('fake-reencryption-request-failed-error'));
};
-export const mockGenerateKFrags = () => {
- return jest.spyOn(Alice.prototype as any, 'generateKFrags');
+export const mockGenerateKFrags = (withValue?: {
+ delegatingKey: PublicKey;
+ verifiedKFrags: VerifiedKeyFrag[];
+}) => {
+ const spy = jest.spyOn(Alice.prototype as any, 'generateKFrags');
+ if (withValue) {
+ return spy.mockImplementation(() => withValue);
+ }
+ return spy;
};
export const mockEncryptTreasureMap = (withValue?: EncryptedTreasureMap) => {
diff --git a/yarn.lock b/yarn.lock
index bf7e3e148..98cab979a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1643,10 +1643,10 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
-"@nucypher/nucypher-core@0.4.0":
- version "0.4.0"
- resolved "https://registry.yarnpkg.com/@nucypher/nucypher-core/-/nucypher-core-0.4.0.tgz#1388abde9de61ed848959b86bc96e3d12ef97ae4"
- integrity sha512-Pu4tRCwf7lnhZSoMjp889uTIUM7bNmYEe05TOOCuMYbJKmQWe7tYKeH0+rflUBISzGtMx2+xDe2CYYTyEGkvSw==
+"@nucypher/nucypher-core@^0.7.0":
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/@nucypher/nucypher-core/-/nucypher-core-0.7.0.tgz#2549364f39087a32be3abd8510baa45c1089d205"
+ integrity sha512-L8jDHIkEPgK4rPOwf7UkePGI/AHnP77TyE7iktO1G/bMGPZzsZ4YVg0Tw13T/3mPLEVjFOFZqA+h75wK3rHU6g==
"@sideway/address@^4.1.3":
version "4.1.4"
From 89a50de8c6dff3ff2dfef22f2724c0425f45daac Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 4 May 2023 13:36:11 +0200
Subject: [PATCH 08/98] handle missing contracts
---
src/agents/contracts.ts | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/src/agents/contracts.ts b/src/agents/contracts.ts
index 79c90bdaf..92c0b12f1 100644
--- a/src/agents/contracts.ts
+++ b/src/agents/contracts.ts
@@ -1,22 +1,22 @@
import { ChainId, ChecksumAddress } from '../types';
type Contracts = {
- readonly SUBSCRIPTION_MANAGER: ChecksumAddress;
- readonly COORDINATOR: ChecksumAddress;
+ readonly SUBSCRIPTION_MANAGER: ChecksumAddress | undefined;
+ readonly COORDINATOR: ChecksumAddress | undefined;
};
const POLYGON: Contracts = {
SUBSCRIPTION_MANAGER: '0xB0194073421192F6Cf38d72c791Be8729721A0b3',
- COORDINATOR: '0x0',
+ COORDINATOR: undefined,
};
const MUMBAI: Contracts = {
SUBSCRIPTION_MANAGER: '0xb9015d7b35ce7c81dde38ef7136baa3b1044f313',
- COORDINATOR: '0x0',
+ COORDINATOR: undefined,
};
const GOERLI: Contracts = {
- SUBSCRIPTION_MANAGER: '0x0',
+ SUBSCRIPTION_MANAGER: undefined,
COORDINATOR: '0x2cf19429168a0943992D8e7dE534E9b802C687B6',
};
@@ -36,7 +36,11 @@ export const getContract = (
if (!Object.keys(CONTRACTS[chainId as ChainId]).includes(contract)) {
throw new Error(`No contract found for name: ${contract}`);
}
- return CONTRACTS[chainId as ChainId][contract];
+ const address = CONTRACTS[chainId as ChainId][contract];
+ if (!address) {
+ throw new Error(`No address found for contract: ${contract}`);
+ }
+ return address;
};
export const DEFAULT_WAIT_N_CONFIRMATIONS = 1;
From 390a3abdddfddc03a3efb4302593c9d42b7f0fba Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 10 May 2023 16:07:37 +0200
Subject: [PATCH 09/98] add index to returnValueTest
---
src/policies/conditions.ts | 3 +++
test/integration/conditions.test.ts | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/src/policies/conditions.ts b/src/policies/conditions.ts
index 80ac8258c..4a6b8dcbf 100644
--- a/src/policies/conditions.ts
+++ b/src/policies/conditions.ts
@@ -118,6 +118,7 @@ export class Condition {
protected makeReturnValueTest() {
return Joi.object({
+ index: Joi.number().required(),
comparator: Joi.string()
.valid(...Condition.COMPARATOR_OPERATORS)
.required(),
@@ -303,6 +304,7 @@ class ERC721Ownership extends EvmCondition {
parameters: [],
standardContractType: 'ERC721',
returnValueTest: {
+ index: 0,
comparator: '==',
value: ':userAddress',
},
@@ -315,6 +317,7 @@ class ERC721Balance extends EvmCondition {
parameters: [':userAddress'],
standardContractType: 'ERC721',
returnValueTest: {
+ index: 0,
comparator: '>',
value: '0',
},
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index 373a2d54e..179c2d836 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -78,6 +78,7 @@ describe('conditions set to/from json', () => {
describe('standard conditions types validation', () => {
const returnValueTest = {
+ index: 0,
comparator: '>',
value: '100',
};
@@ -123,6 +124,7 @@ describe('standard conditions types validation', () => {
const badTimelockCondition = {
// Intentionally replacing `returnValueTest` with an invalid test
returnValueTest: {
+ index: 0,
comparator: 'not-a-comparator',
value: '100',
},
@@ -191,6 +193,7 @@ describe('produce context parameters from conditions', () => {
method,
parameters: [contextParam],
returnValueTest: {
+ index: 0,
comparator: '==',
value: contextParam,
},
@@ -224,6 +227,7 @@ describe('produce context parameters from conditions', () => {
method: 'balanceOf',
parameters: [contextParam],
returnValueTest: {
+ index: 0,
comparator: '==',
value: contextParam,
},
@@ -246,6 +250,7 @@ describe('condition context', () => {
method: 'eth_getBalance',
parameters: [':userAddress'],
returnValueTest: {
+ index: 0,
comparator: '==',
value: ':userAddress',
},
@@ -269,6 +274,7 @@ describe('evm condition', () => {
method: 'balanceOf',
parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
returnValueTest: {
+ index: 0,
comparator: '==',
value: ':userAddress',
},
From ad52ec174de3ad0ce1118b2fba7df47a96c262fb Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 10 May 2023 17:51:16 +0200
Subject: [PATCH 10/98] feat: make index in return value test optional
---
src/policies/conditions.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/policies/conditions.ts b/src/policies/conditions.ts
index 4a6b8dcbf..bfa3ca97f 100644
--- a/src/policies/conditions.ts
+++ b/src/policies/conditions.ts
@@ -118,7 +118,7 @@ export class Condition {
protected makeReturnValueTest() {
return Joi.object({
- index: Joi.number().required(),
+ index: Joi.number().optional(),
comparator: Joi.string()
.valid(...Condition.COMPARATOR_OPERATORS)
.required(),
From fa287d6132155fa9a453b0f6e3afc76bd36b57eb Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 10 May 2023 17:47:33 +0200
Subject: [PATCH 11/98] feat: support user-provided params in condition context
---
src/policies/conditions.ts | 64 +++++++++++++++------
test/integration/conditions.test.ts | 89 ++++++++++++++++++++++++-----
2 files changed, 122 insertions(+), 31 deletions(-)
diff --git a/src/policies/conditions.ts b/src/policies/conditions.ts
index bfa3ca97f..64a262c1f 100644
--- a/src/policies/conditions.ts
+++ b/src/policies/conditions.ts
@@ -192,6 +192,9 @@ const makeGuard = (
return schema;
};
+export const USER_ADDRESS_PARAM = ':userAddress';
+export const SPECIAL_CONTEXT_PARAMS = [USER_ADDRESS_PARAM];
+
class TimelockCondition extends Condition {
public static readonly CONDITION_TYPE = 'timelock';
@@ -216,8 +219,8 @@ class RpcCondition extends Condition {
string,
string[]
> = {
- eth_getBalance: [':userAddress'],
- balanceOf: [':userAddress'],
+ eth_getBalance: [USER_ADDRESS_PARAM],
+ balanceOf: [USER_ADDRESS_PARAM],
};
public readonly schema = Joi.object({
@@ -258,7 +261,7 @@ class EvmCondition extends Condition {
public static readonly METHODS_PER_CONTRACT_TYPE: Record = {
ERC20: ['balanceOf'],
ERC721: ['balanceOf', 'ownerOf'],
- ERC1155: ['balanceOf'],
+ // ERC1155: ['balanceOf'], // TODO(#131)
};
public static readonly PARAMETERS_PER_METHOD: Record = {
balanceOf: ['address'],
@@ -268,8 +271,8 @@ class EvmCondition extends Condition {
string,
string[]
> = {
- balanceOf: [':userAddress'],
- ownerOf: [':userAddress'],
+ balanceOf: [USER_ADDRESS_PARAM],
+ ownerOf: [USER_ADDRESS_PARAM],
};
private makeMethod = () =>
@@ -306,7 +309,7 @@ class ERC721Ownership extends EvmCondition {
returnValueTest: {
index: 0,
comparator: '==',
- value: ':userAddress',
+ value: USER_ADDRESS_PARAM,
},
};
}
@@ -314,7 +317,7 @@ class ERC721Ownership extends EvmCondition {
class ERC721Balance extends EvmCondition {
readonly defaults = {
method: 'balanceOf',
- parameters: [':userAddress'],
+ parameters: [USER_ADDRESS_PARAM],
standardContractType: 'ERC721',
returnValueTest: {
index: 0,
@@ -330,13 +333,24 @@ interface TypedSignature {
address: string;
}
+export type CustomContextParam = string | number | boolean;
+
export class ConditionContext {
private walletSignature?: Record;
constructor(
private readonly conditions: WASMConditions,
- private readonly web3Provider: ethers.providers.Web3Provider
- ) {}
+ private readonly web3Provider: ethers.providers.Web3Provider,
+ public readonly customParameters: Record = {}
+ ) {
+ Object.keys(customParameters).forEach((key) => {
+ if (SPECIAL_CONTEXT_PARAMS.includes(key)) {
+ throw new Error(
+ `Cannot use reserved parameter name ${key} as custom parameter`
+ );
+ }
+ });
+ }
public async getOrCreateWalletSignature(): Promise {
const address = await this.web3Provider.getSigner().getAddress();
@@ -443,16 +457,34 @@ export class ConditionContext {
}
public toJson = async (): Promise => {
- const userAddressParam = this.conditions
- .toString()
- .includes(':userAddress');
- if (!userAddressParam) {
- return JSON.stringify({});
+ const payload: Record = {};
+ if (this.conditions.toString().includes(USER_ADDRESS_PARAM)) {
+ payload[USER_ADDRESS_PARAM] = await this.getOrCreateWalletSignature();
}
- const typedSignature = await this.getOrCreateWalletSignature();
- const payload = { ':userAddress': typedSignature };
+
+ const conditions = JSON.parse(this.conditions.toString());
+ conditions.forEach((cond: { parameters: string[] }) => {
+ cond.parameters.forEach((key) => {
+ if (
+ !(key in this.customParameters) &&
+ !SPECIAL_CONTEXT_PARAMS.includes(key)
+ ) {
+ throw new Error(`Missing custom context parameter ${key}`);
+ }
+ });
+ });
+
+ Object.keys(this.customParameters).forEach((key) => {
+ payload[key] = this.customParameters[key];
+ });
return JSON.stringify(payload);
};
+
+ public withCustomParams = (
+ params: Record
+ ): ConditionContext => {
+ return new ConditionContext(this.conditions, this.web3Provider, params);
+ };
}
const OR = new Operator('or');
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index 881b0cb10..d65b842f5 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -6,8 +6,13 @@ import {
ConditionSet,
Operator,
} from '../../src';
+import { USER_ADDRESS_PARAM } from '../../src/policies/conditions';
import { fakeWeb3Provider } from '../utils';
+const TEST_CONTRACT_ADDR = '0xC36442b4a4522E871399CD717aBDD847Ab11FE88';
+const TEST_CONTRACT_ADDR_2 = '0x5dB11d7356aa4C0E85Aa5b255eC2B5F81De6d4dA';
+const TEST_CHAIN_ID = 5;
+
describe('operator', () => {
it('should validate Operator', async () => {
const op = new Operator('or');
@@ -21,20 +26,18 @@ describe('operator', () => {
describe('conditions schema', () => {
const condition = new Conditions.ERC721Balance();
let result = condition.validate({
- contractAddress: '0xC36442b4a4522E871399CD717aBDD847Ab11FE88',
+ contractAddress: TEST_CONTRACT_ADDR,
});
it('should validate', async () => {
expect(result.error).toEqual(undefined);
- expect(result.value.contractAddress).toEqual(
- '0xC36442b4a4522E871399CD717aBDD847Ab11FE88'
- );
+ expect(result.value.contractAddress).toEqual(TEST_CONTRACT_ADDR);
});
- result = condition.validate({ chain: 5 });
+ result = condition.validate({ chain: TEST_CHAIN_ID });
it('should update the value of "chain"', async () => {
expect(result.error).toEqual(undefined);
- expect(result.value.chain).toEqual(5);
+ expect(result.value.chain).toEqual(TEST_CHAIN_ID);
});
it('should validate chain id', async () => {
@@ -47,10 +50,10 @@ describe('conditions schema', () => {
describe('condition set', () => {
const genuineUndead = new Conditions.ERC721Balance({
- contractAddress: '0x209e639a0EC166Ac7a1A4bA41968fa967dB30221',
+ contractAddress: TEST_CONTRACT_ADDR,
});
const gnomePals = new Conditions.ERC721Balance({
- contractAddress: '0x5dB11d7356aa4C0E85Aa5b255eC2B5F81De6d4dA',
+ contractAddress: TEST_CONTRACT_ADDR_2,
});
const conditions = new ConditionSet([
genuineUndead,
@@ -64,13 +67,12 @@ describe('condition set', () => {
});
describe('conditions set to/from json', () => {
- const json =
- '[{"chain":5,"method":"ownerOf","parameters":["3591"],"standardContractType":"ERC721","returnValueTest":{"comparator":"==","value":":userAddress"},"contractAddress":"0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77"}]';
+ const json = `[{"chain":${TEST_CHAIN_ID},"method":"ownerOf","parameters":["3591"],"standardContractType":"ERC721","returnValueTest":{"comparator":"==","value":":userAddress"},"contractAddress":"${TEST_CONTRACT_ADDR}"}]`;
const conditionSet = ConditionSet.fromJSON(json);
it('should be a ConditionSet', async () => {
expect(conditionSet.conditions[0].toObj().contractAddress).toEqual(
- '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'
+ TEST_CONTRACT_ADDR
);
expect(conditionSet.toJson()).toEqual(json);
});
@@ -248,11 +250,11 @@ describe('condition context', () => {
const rpcCondition = new Conditions.RpcCondition({
chain: 5,
method: 'eth_getBalance',
- parameters: [':userAddress'],
+ parameters: [USER_ADDRESS_PARAM],
returnValueTest: {
index: 0,
comparator: '==',
- value: ':userAddress',
+ value: USER_ADDRESS_PARAM,
},
});
const conditionSet = new ConditionSet([rpcCondition]);
@@ -262,7 +264,64 @@ describe('condition context', () => {
web3Provider
);
const asJson = await conditionContext.toJson();
- expect(asJson).toBeDefined();
+ expect(asJson).toContain(USER_ADDRESS_PARAM);
+ });
+
+ describe('supports user-defined parameters', () => {
+ const fakeFunctionAbi = {
+ name: 'myFunction',
+ type: 'function',
+ inputs: [
+ {
+ name: 'account',
+ type: 'address',
+ },
+ {
+ name: 'myCustomParam',
+ type: 'uint256',
+ },
+ ],
+ outputs: [
+ {
+ name: 'someValue',
+ type: 'uint256',
+ },
+ ],
+ };
+ const evmCondition = new Conditions.EvmCondition({
+ chain: 5,
+ functionAbi: fakeFunctionAbi,
+ method: 'balanceOf',
+ contractAddress: '0x0000000000000000000000000000000000000000',
+ parameters: [USER_ADDRESS_PARAM, ':customParam'],
+ returnValueTest: {
+ index: 0,
+ comparator: '==',
+ value: USER_ADDRESS_PARAM,
+ },
+ });
+ const web3Provider = mockWeb3Provider(SecretKey.random().toBEBytes());
+ const conditionSet = new ConditionSet([evmCondition]);
+ const conditionContext = new ConditionContext(
+ conditionSet.toWASMConditions(),
+ web3Provider
+ );
+
+ it('parses user-provided context parameters', async () => {
+ const customParams = { ':customParam': 0 };
+ const asJson = await conditionContext
+ .withCustomParams(customParams)
+ .toJson();
+ expect(asJson).toBeDefined();
+ expect(asJson).toContain(USER_ADDRESS_PARAM);
+ expect(asJson).toContain(':customParam');
+ });
+
+ it('throws on missing custom context param', async () => {
+ await expect(conditionContext.toJson()).rejects.toThrow(
+ 'Missing custom context parameter :customParam'
+ );
+ });
});
});
@@ -276,7 +335,7 @@ describe('evm condition', () => {
returnValueTest: {
index: 0,
comparator: '==',
- value: ':userAddress',
+ value: USER_ADDRESS_PARAM,
},
};
const standardContractType = 'ERC20';
From 9ebd7475a16fa020a580760b0b3b0cf76d3d27ac Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 10 May 2023 17:53:29 +0200
Subject: [PATCH 12/98] fix after rebase
---
test/integration/conditions.test.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index d65b842f5..a6edd52d5 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -300,7 +300,7 @@ describe('condition context', () => {
value: USER_ADDRESS_PARAM,
},
});
- const web3Provider = mockWeb3Provider(SecretKey.random().toBEBytes());
+ const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
const conditionSet = new ConditionSet([evmCondition]);
const conditionContext = new ConditionContext(
conditionSet.toWASMConditions(),
From 97e61b2fdc86ac3132073b111eb4e792e99018a3 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 10 May 2023 18:07:50 +0200
Subject: [PATCH 13/98] test custom param validation
---
test/integration/conditions.test.ts | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index a6edd52d5..3083a996e 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -6,7 +6,10 @@ import {
ConditionSet,
Operator,
} from '../../src';
-import { USER_ADDRESS_PARAM } from '../../src/policies/conditions';
+import {
+ CustomContextParam,
+ USER_ADDRESS_PARAM,
+} from '../../src/policies/conditions';
import { fakeWeb3Provider } from '../utils';
const TEST_CONTRACT_ADDR = '0xC36442b4a4522E871399CD717aBDD847Ab11FE88';
@@ -306,20 +309,31 @@ describe('condition context', () => {
conditionSet.toWASMConditions(),
web3Provider
);
+ const myCustomParam = ':customParam';
it('parses user-provided context parameters', async () => {
- const customParams = { ':customParam': 0 };
+ const customParams: Record = {};
+ customParams[myCustomParam] = 1234;
const asJson = await conditionContext
.withCustomParams(customParams)
.toJson();
expect(asJson).toBeDefined();
expect(asJson).toContain(USER_ADDRESS_PARAM);
- expect(asJson).toContain(':customParam');
+ expect(asJson).toContain(myCustomParam);
});
it('throws on missing custom context param', async () => {
await expect(conditionContext.toJson()).rejects.toThrow(
- 'Missing custom context parameter :customParam'
+ `Missing custom context parameter ${myCustomParam}`
+ );
+ });
+
+ it('throws on using reserved context parameter identifiers', () => {
+ const badCustomParams: Record = {};
+ badCustomParams[USER_ADDRESS_PARAM] = 'this-will-throw';
+
+ expect(() => conditionContext.withCustomParams(badCustomParams)).toThrow(
+ `Cannot use reserved parameter name ${USER_ADDRESS_PARAM} as custom parameter`
);
});
});
From c71b37a65dc2e76efb109b9b46ab51a44006a591 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 10 May 2023 19:59:49 +0200
Subject: [PATCH 14/98] refactor conditions dir structure
---
src/characters/enrico.ts | 2 +-
src/characters/porter.ts | 2 +-
src/characters/universal-bob.ts | 2 +-
src/conditions/condition-context.ts | 167 +++++++++
src/conditions/condition-set.ts | 64 ++++
src/conditions/conditions.ts | 248 ++++++++++++++
src/conditions/operator.ts | 20 ++
src/index.ts | 10 +-
src/policies/conditions.ts | 502 ----------------------------
src/sdk/strategy.ts | 2 +-
test/integration/conditions.test.ts | 12 +-
test/integration/pre.test.ts | 2 +-
12 files changed, 512 insertions(+), 521 deletions(-)
create mode 100644 src/conditions/condition-context.ts
create mode 100644 src/conditions/condition-set.ts
create mode 100644 src/conditions/conditions.ts
create mode 100644 src/conditions/operator.ts
delete mode 100644 src/policies/conditions.ts
diff --git a/src/characters/enrico.ts b/src/characters/enrico.ts
index bf79b269b..cd8bed5bc 100644
--- a/src/characters/enrico.ts
+++ b/src/characters/enrico.ts
@@ -1,7 +1,7 @@
import { MessageKit, PublicKey, SecretKey } from '@nucypher/nucypher-core';
+import { ConditionSet } from '../conditions/condition-set';
import { Keyring } from '../keyring';
-import { ConditionSet } from '../policies/conditions';
import { toBytes } from '../utils';
export class Enrico {
diff --git a/src/characters/porter.ts b/src/characters/porter.ts
index ee0df9a40..243262919 100644
--- a/src/characters/porter.ts
+++ b/src/characters/porter.ts
@@ -7,7 +7,7 @@ import {
import axios, { AxiosResponse } from 'axios';
import qs from 'qs';
-import { ConditionContext } from '../policies/conditions';
+import { ConditionContext } from '../conditions/condition-context';
import { Base64EncodedBytes, ChecksumAddress, HexEncodedBytes } from '../types';
import { fromBase64, fromHexString, toBase64, toHexString } from '../utils';
diff --git a/src/characters/universal-bob.ts b/src/characters/universal-bob.ts
index 3bdbb95d7..68c8bdfcd 100644
--- a/src/characters/universal-bob.ts
+++ b/src/characters/universal-bob.ts
@@ -8,10 +8,10 @@ import {
} from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
+import { ConditionSet } from '../conditions/condition-set';
import { Keyring } from '../keyring';
import { PolicyMessageKit } from '../kits/message';
import { RetrievalResult } from '../kits/retrieval';
-import { ConditionSet } from '../policies/conditions';
import { base64ToU8Receiver, u8ToBase64Replacer, zip } from '../utils';
import { Porter } from './porter';
diff --git a/src/conditions/condition-context.ts b/src/conditions/condition-context.ts
new file mode 100644
index 000000000..3e52e6f19
--- /dev/null
+++ b/src/conditions/condition-context.ts
@@ -0,0 +1,167 @@
+import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
+import { ethers } from 'ethers';
+import { utils as ethersUtils } from 'ethers/lib/ethers';
+
+import { Eip712TypedData, FormattedTypedData } from '../web3';
+
+import { SPECIAL_CONTEXT_PARAMS, USER_ADDRESS_PARAM } from './conditions';
+
+interface TypedSignature {
+ signature: string;
+ typedData: Eip712TypedData;
+ address: string;
+}
+
+export type CustomContextParam = string | number | boolean;
+
+export class ConditionContext {
+ private walletSignature?: Record;
+
+ constructor(
+ private readonly conditions: WASMConditions,
+ private readonly web3Provider: ethers.providers.Web3Provider,
+ public readonly customParameters: Record = {}
+ ) {
+ Object.keys(customParameters).forEach((key) => {
+ if (SPECIAL_CONTEXT_PARAMS.includes(key)) {
+ throw new Error(
+ `Cannot use reserved parameter name ${key} as custom parameter`
+ );
+ }
+ });
+ }
+
+ public async getOrCreateWalletSignature(): Promise {
+ const address = await this.web3Provider.getSigner().getAddress();
+ const storageKey = `wallet-signature-${address}`;
+
+ // If we have a signature in localStorage, return it
+ const isLocalStorage = typeof localStorage !== 'undefined';
+ if (isLocalStorage) {
+ const maybeSignature = localStorage.getItem(storageKey);
+ if (maybeSignature) {
+ return JSON.parse(maybeSignature);
+ }
+ }
+
+ // If not, try returning from memory
+ const maybeSignature = this.walletSignature?.[address];
+ if (maybeSignature) {
+ if (isLocalStorage) {
+ localStorage.setItem(storageKey, maybeSignature);
+ }
+ return JSON.parse(maybeSignature);
+ }
+
+ // If at this point we didn't return, we need to create a new signature
+ const typedSignature = await this.createWalletSignature();
+
+ // Persist where you can
+ if (isLocalStorage) {
+ localStorage.setItem(storageKey, JSON.stringify(typedSignature));
+ }
+ if (!this.walletSignature) {
+ this.walletSignature = {};
+ }
+ this.walletSignature[address] = JSON.stringify(typedSignature);
+ return typedSignature;
+ }
+
+ private async createWalletSignature(): Promise {
+ // Ensure freshness of the signature
+ const { blockNumber, blockHash, chainId } = await this.getChainData();
+ const address = await this.web3Provider.getSigner().getAddress();
+ const signatureText = `I'm the owner of address ${address} as of block number ${blockNumber}`;
+ const salt = ethersUtils.hexlify(ethersUtils.randomBytes(32));
+
+ const typedData: Eip712TypedData = {
+ types: {
+ Wallet: [
+ { name: 'address', type: 'address' },
+ { name: 'signatureText', type: 'string' },
+ { name: 'blockNumber', type: 'uint256' },
+ { name: 'blockHash', type: 'bytes32' },
+ ],
+ },
+ domain: {
+ name: 'tDec',
+ version: '1',
+ chainId,
+ salt,
+ },
+ message: {
+ address,
+ signatureText,
+ blockNumber,
+ blockHash,
+ },
+ };
+ const signature = await this.web3Provider
+ .getSigner()
+ ._signTypedData(typedData.domain, typedData.types, typedData.message);
+
+ const formattedTypedData: FormattedTypedData = {
+ ...typedData,
+ primaryType: 'Wallet',
+ types: {
+ ...typedData.types,
+ EIP712Domain: [
+ {
+ name: 'name',
+ type: 'string',
+ },
+ {
+ name: 'version',
+ type: 'string',
+ },
+ {
+ name: 'chainId',
+ type: 'uint256',
+ },
+ {
+ name: 'salt',
+ type: 'bytes32',
+ },
+ ],
+ },
+ };
+ return { signature, typedData: formattedTypedData, address };
+ }
+
+ private async getChainData() {
+ const blockNumber = await this.web3Provider.getBlockNumber();
+ const blockHash = (await this.web3Provider.getBlock(blockNumber)).hash;
+ const chainId = (await this.web3Provider.getNetwork()).chainId;
+ return { blockNumber, blockHash, chainId };
+ }
+
+ public toJson = async (): Promise => {
+ const payload: Record = {};
+ if (this.conditions.toString().includes(USER_ADDRESS_PARAM)) {
+ payload[USER_ADDRESS_PARAM] = await this.getOrCreateWalletSignature();
+ }
+
+ const conditions = JSON.parse(this.conditions.toString());
+ conditions.forEach((cond: { parameters: string[] }) => {
+ cond.parameters.forEach((key) => {
+ if (
+ !(key in this.customParameters) &&
+ !SPECIAL_CONTEXT_PARAMS.includes(key)
+ ) {
+ throw new Error(`Missing custom context parameter ${key}`);
+ }
+ });
+ });
+
+ Object.keys(this.customParameters).forEach((key) => {
+ payload[key] = this.customParameters[key];
+ });
+ return JSON.stringify(payload);
+ };
+
+ public withCustomParams = (
+ params: Record
+ ): ConditionContext => {
+ return new ConditionContext(this.conditions, this.web3Provider, params);
+ };
+}
diff --git a/src/conditions/condition-set.ts b/src/conditions/condition-set.ts
new file mode 100644
index 000000000..f8d21e966
--- /dev/null
+++ b/src/conditions/condition-set.ts
@@ -0,0 +1,64 @@
+import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
+import { ethers } from 'ethers';
+
+import { ConditionContext } from './condition-context';
+import { Condition } from './conditions';
+import { Operator } from './operator';
+
+export class ConditionSet {
+ constructor(
+ public readonly conditions: ReadonlyArray
+ ) {}
+
+ public validate() {
+ if (this.conditions.length % 2 === 0) {
+ throw new Error(
+ 'conditions must be odd length, ever other element being an operator'
+ );
+ }
+ this.conditions.forEach((cnd: Condition | Operator, index) => {
+ if (index % 2 && cnd.constructor.name !== 'Operator')
+ throw new Error(
+ `${index} element must be an Operator; Got ${cnd.constructor.name}.`
+ );
+ if (!(index % 2) && cnd.constructor.name === 'Operator')
+ throw new Error(
+ `${index} element must be a Condition; Got ${cnd.constructor.name}.`
+ );
+ });
+ return true;
+ }
+
+ public toList() {
+ return this.conditions.map((cnd) => {
+ return cnd.toObj();
+ });
+ }
+
+ public static fromList(list: ReadonlyArray>) {
+ return new ConditionSet(
+ list.map((ele: Record) => {
+ if ('operator' in ele) return Operator.fromObj(ele);
+ return Condition.fromObj(ele);
+ })
+ );
+ }
+
+ public toJson() {
+ return JSON.stringify(this.toList());
+ }
+
+ public static fromJSON(json: string) {
+ return ConditionSet.fromList(JSON.parse(json));
+ }
+
+ public toWASMConditions() {
+ return new WASMConditions(this.toJson());
+ }
+
+ public buildContext(
+ provider: ethers.providers.Web3Provider
+ ): ConditionContext {
+ return new ConditionContext(this.toWASMConditions(), provider);
+ }
+}
diff --git a/src/conditions/conditions.ts b/src/conditions/conditions.ts
new file mode 100644
index 000000000..1dcf5765d
--- /dev/null
+++ b/src/conditions/conditions.ts
@@ -0,0 +1,248 @@
+import Joi, { ValidationError } from 'joi';
+
+export class Condition {
+ public static readonly COMPARATOR_OPERATORS = [
+ '==',
+ '>',
+ '<',
+ '>=',
+ '<=',
+ '!=',
+ ];
+
+ public static readonly SUPPORTED_CHAINS = [
+ 1, // ethereum/mainnet
+ 5, // ethereum/goerli
+ 137, // polygon/mainnet
+ 80001, // polygon/mumbai
+ ];
+
+ public readonly schema = Joi.object();
+ public readonly defaults = {};
+ private validationError?: ValidationError;
+
+ constructor(private readonly value: Record = {}) {}
+
+ public get error(): string | undefined {
+ return this.validationError?.message;
+ }
+
+ protected makeReturnValueTest() {
+ return Joi.object({
+ index: Joi.number().optional(),
+ comparator: Joi.string()
+ .valid(...Condition.COMPARATOR_OPERATORS)
+ .required(),
+ value: Joi.alternatives(Joi.string(), Joi.number()).required(),
+ });
+ }
+
+ public toObj(): Record {
+ const { error, value } = this.validate();
+ if (error) {
+ throw Error(error.message);
+ }
+ return value;
+ }
+
+ public static fromObj(obj: Record) {
+ return new Condition(obj);
+ }
+
+ public validate(data: Record = {}) {
+ const newValue = Object.assign(this.defaults, this.value, data);
+ return this.schema.validate(newValue);
+ }
+
+ public getContextParameters(): string[] {
+ // Check all the places where context parameters may be hiding
+ const asObject = this.toObj();
+ let paramsToCheck: string[] = [];
+
+ // They may be hiding in the method parameters
+ const method = asObject['method'] as string;
+ if (method) {
+ const contextParams = RpcCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
+ paramsToCheck = [...(contextParams ?? [])];
+ }
+
+ // Or in the ReturnValue test
+ const returnValueTest = asObject['returnValueTest'] as Record<
+ string,
+ string
+ >;
+ if (returnValueTest) {
+ paramsToCheck.push(returnValueTest['value']);
+ }
+
+ // Merge & deduplicate found context parameters
+ paramsToCheck = [
+ ...paramsToCheck,
+ ...((asObject['parameters'] as string[]) ?? []),
+ ];
+ const withoutDuplicates = new Set(
+ paramsToCheck.filter((p) => paramsToCheck.includes(p))
+ );
+ return [...withoutDuplicates];
+ }
+}
+
+// A helper method for making complex Joi types
+// It says "allow these `types` when `parent` value is given"
+const makeGuard = (
+ schema: Joi.StringSchema | Joi.ArraySchema,
+ types: Record,
+ parent: string
+) => {
+ Object.entries(types).forEach(([key, value]) => {
+ schema = schema.when(parent, {
+ is: key,
+ then: value,
+ });
+ });
+ return schema;
+};
+
+export const USER_ADDRESS_PARAM = ':userAddress';
+export const SPECIAL_CONTEXT_PARAMS = [USER_ADDRESS_PARAM];
+
+class TimelockCondition extends Condition {
+ public static readonly CONDITION_TYPE = 'timelock';
+
+ defaults = {
+ method: 'timelock',
+ };
+
+ public readonly schema = Joi.object({
+ returnValueTest: this.makeReturnValueTest(),
+ method: 'timelock',
+ });
+}
+
+class RpcCondition extends Condition {
+ public static readonly CONDITION_TYPE = 'rpc';
+ public static readonly RPC_METHODS = ['eth_getBalance', 'balanceOf'];
+ public static readonly PARAMETERS_PER_METHOD: Record = {
+ eth_getBalance: ['address'],
+ balanceOf: ['address'],
+ };
+ public static readonly CONTEXT_PARAMETERS_PER_METHOD: Record<
+ string,
+ string[]
+ > = {
+ eth_getBalance: [USER_ADDRESS_PARAM],
+ balanceOf: [USER_ADDRESS_PARAM],
+ };
+
+ public readonly schema = Joi.object({
+ chain: Joi.number()
+ .valid(...Condition.SUPPORTED_CHAINS)
+ .required(),
+ method: Joi.string()
+ .valid(...RpcCondition.RPC_METHODS)
+ .required(),
+ parameters: Joi.array().required(),
+ returnValueTest: this.makeReturnValueTest(),
+ });
+
+ public getContextParameters = (): string[] => {
+ const asObject = this.toObj();
+
+ const method = asObject['method'] as string;
+ const parameters = (asObject['parameters'] ?? []) as string[];
+
+ const context = RpcCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
+ const returnValueTest = asObject['returnValueTest'] as Record<
+ string,
+ string
+ >;
+
+ const maybeParams = [...(context ?? []), returnValueTest['value']];
+ return parameters.filter((p) => maybeParams.includes(p));
+ };
+}
+
+class EvmCondition extends Condition {
+ public static readonly CONDITION_TYPE = 'evm';
+ public static readonly STANDARD_CONTRACT_TYPES = [
+ 'ERC20',
+ 'ERC721',
+ // 'ERC1155', // TODO(#131)
+ ];
+ public static readonly METHODS_PER_CONTRACT_TYPE: Record = {
+ ERC20: ['balanceOf'],
+ ERC721: ['balanceOf', 'ownerOf'],
+ // ERC1155: ['balanceOf'], // TODO(#131)
+ };
+ public static readonly PARAMETERS_PER_METHOD: Record = {
+ balanceOf: ['address'],
+ ownerOf: ['tokenId'],
+ };
+ public static readonly CONTEXT_PARAMETERS_PER_METHOD: Record<
+ string,
+ string[]
+ > = {
+ balanceOf: [USER_ADDRESS_PARAM],
+ ownerOf: [USER_ADDRESS_PARAM],
+ };
+
+ private makeMethod = () =>
+ makeGuard(
+ Joi.string(),
+ EvmCondition.METHODS_PER_CONTRACT_TYPE,
+ 'standardContractType'
+ );
+
+ public readonly schema = Joi.object({
+ contractAddress: Joi.string()
+ .pattern(new RegExp('^0x[a-fA-F0-9]{40}$'))
+ .required(),
+ chain: Joi.string()
+ .valid(...Condition.SUPPORTED_CHAINS)
+ .required(),
+ standardContractType: Joi.string()
+ .valid(...EvmCondition.STANDARD_CONTRACT_TYPES)
+ .optional(),
+ functionAbi: Joi.object().optional(),
+ method: this.makeMethod().required(),
+ parameters: Joi.array().required(),
+ returnValueTest: this.makeReturnValueTest(),
+ })
+ // At most one of these keys needs to be present
+ .xor('standardContractType', 'functionAbi');
+}
+
+class ERC721Ownership extends EvmCondition {
+ readonly defaults = {
+ method: 'ownerOf',
+ parameters: [],
+ standardContractType: 'ERC721',
+ returnValueTest: {
+ index: 0,
+ comparator: '==',
+ value: USER_ADDRESS_PARAM,
+ },
+ };
+}
+
+class ERC721Balance extends EvmCondition {
+ readonly defaults = {
+ method: 'balanceOf',
+ parameters: [USER_ADDRESS_PARAM],
+ standardContractType: 'ERC721',
+ returnValueTest: {
+ index: 0,
+ comparator: '>',
+ value: '0',
+ },
+ };
+}
+
+export const Conditions = {
+ ERC721Ownership,
+ ERC721Balance,
+ EvmCondition,
+ TimelockCondition,
+ RpcCondition,
+ Condition,
+};
diff --git a/src/conditions/operator.ts b/src/conditions/operator.ts
new file mode 100644
index 000000000..e7fdca994
--- /dev/null
+++ b/src/conditions/operator.ts
@@ -0,0 +1,20 @@
+export class Operator {
+ static readonly LOGICAL_OPERATORS: ReadonlyArray = ['and', 'or'];
+ static readonly AND = new Operator('and');
+ static readonly OR = new Operator('or');
+
+ public constructor(public readonly operator: string) {
+ if (!Operator.LOGICAL_OPERATORS.includes(operator)) {
+ throw `"${operator}" is not a valid operator`;
+ }
+ this.operator = operator;
+ }
+
+ toObj() {
+ return { operator: this.operator };
+ }
+
+ static fromObj(obj: Record) {
+ return new Operator(obj.operator);
+ }
+}
diff --git a/src/index.ts b/src/index.ts
index 5aa9d2005..83dffc869 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -12,13 +12,13 @@ export { Keyring } from './keyring';
export { Configuration, defaultConfiguration } from './config';
export { RevocationKit } from './kits/revocation';
export { PolicyMessageKit } from './kits/message';
+export { Conditions, Condition } from './conditions/conditions';
+export { Operator } from './conditions/operator';
+export { ConditionSet } from './conditions/condition-set';
export {
- Conditions,
- ConditionSet,
ConditionContext,
- Operator,
- Condition,
-} from './policies/conditions';
+ CustomContextParam,
+} from './conditions/condition-context';
export { Cohort } from './sdk/cohort';
export { DeployedStrategy, RevokedStrategy, Strategy } from './sdk/strategy';
diff --git a/src/policies/conditions.ts b/src/policies/conditions.ts
deleted file mode 100644
index 64a262c1f..000000000
--- a/src/policies/conditions.ts
+++ /dev/null
@@ -1,502 +0,0 @@
-import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
-import { ethers, utils as ethersUtils } from 'ethers';
-import Joi, { ValidationError } from 'joi';
-
-import { Eip712TypedData, FormattedTypedData } from '../web3';
-
-export class Operator {
- static readonly LOGICAL_OPERATORS: ReadonlyArray = ['and', 'or'];
-
- public constructor(public readonly operator: string) {
- if (!Operator.LOGICAL_OPERATORS.includes(operator)) {
- throw `"${operator}" is not a valid operator`;
- }
- this.operator = operator;
- }
-
- toObj() {
- return { operator: this.operator };
- }
-
- static fromObj(obj: Record) {
- return new Operator(obj.operator);
- }
-
- public static AND() {
- return new Operator('and');
- }
-
- public static OR() {
- return new Operator('or');
- }
-}
-
-export class ConditionSet {
- constructor(
- public readonly conditions: ReadonlyArray
- ) {}
-
- public validate() {
- if (this.conditions.length % 2 === 0) {
- throw new Error(
- 'conditions must be odd length, ever other element being an operator'
- );
- }
- this.conditions.forEach((cnd: Condition | Operator, index) => {
- if (index % 2 && cnd.constructor.name !== 'Operator')
- throw new Error(
- `${index} element must be an Operator; Got ${cnd.constructor.name}.`
- );
- if (!(index % 2) && cnd.constructor.name === 'Operator')
- throw new Error(
- `${index} element must be a Condition; Got ${cnd.constructor.name}.`
- );
- });
- return true;
- }
-
- public toList() {
- return this.conditions.map((cnd) => {
- return cnd.toObj();
- });
- }
-
- public static fromList(list: ReadonlyArray>) {
- return new ConditionSet(
- list.map((ele: Record) => {
- if ('operator' in ele) return Operator.fromObj(ele);
- return Condition.fromObj(ele);
- })
- );
- }
-
- public toJson() {
- return JSON.stringify(this.toList());
- }
-
- public static fromJSON(json: string) {
- return ConditionSet.fromList(JSON.parse(json));
- }
-
- public toWASMConditions() {
- return new WASMConditions(this.toJson());
- }
-
- public buildContext(
- provider: ethers.providers.Web3Provider
- ): ConditionContext {
- return new ConditionContext(this.toWASMConditions(), provider);
- }
-}
-
-export class Condition {
- public static readonly COMPARATOR_OPERATORS = [
- '==',
- '>',
- '<',
- '>=',
- '<=',
- '!=',
- ];
-
- public static readonly SUPPORTED_CHAINS = [
- 1, // ethereum/mainnet
- 5, // ethereum/goerli
- 137, // polygon/mainnet
- 80001, // polygon/mumbai
- ];
-
- public readonly schema = Joi.object();
- public readonly defaults = {};
- private validationError?: ValidationError;
-
- constructor(private readonly value: Record = {}) {}
-
- public get error(): string | undefined {
- return this.validationError?.message;
- }
-
- protected makeReturnValueTest() {
- return Joi.object({
- index: Joi.number().optional(),
- comparator: Joi.string()
- .valid(...Condition.COMPARATOR_OPERATORS)
- .required(),
- value: Joi.alternatives(Joi.string(), Joi.number()).required(),
- });
- }
-
- public toObj(): Record {
- const { error, value } = this.validate();
- if (error) {
- throw Error(error.message);
- }
- return value;
- }
-
- public static fromObj(obj: Record) {
- return new Condition(obj);
- }
-
- public validate(data: Record = {}) {
- const newValue = Object.assign(this.defaults, this.value, data);
- return this.schema.validate(newValue);
- }
-
- public getContextParameters(): string[] {
- // Check all the places where context parameters may be hiding
- const asObject = this.toObj();
- let paramsToCheck: string[] = [];
-
- // They may be hiding in the method parameters
- const method = asObject['method'] as string;
- if (method) {
- const contextParams = RpcCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
- paramsToCheck = [...(contextParams ?? [])];
- }
-
- // Or in the ReturnValue test
- const returnValueTest = asObject['returnValueTest'] as Record<
- string,
- string
- >;
- if (returnValueTest) {
- paramsToCheck.push(returnValueTest['value']);
- }
-
- // Merge & deduplicate found context parameters
- paramsToCheck = [
- ...paramsToCheck,
- ...((asObject['parameters'] as string[]) ?? []),
- ];
- const withoutDuplicates = new Set(
- paramsToCheck.filter((p) => paramsToCheck.includes(p))
- );
- return [...withoutDuplicates];
- }
-}
-
-// A helper method for making complex Joi types
-// It says "allow these `types` when `parent` value is given"
-const makeGuard = (
- schema: Joi.StringSchema | Joi.ArraySchema,
- types: Record,
- parent: string
-) => {
- Object.entries(types).forEach(([key, value]) => {
- schema = schema.when(parent, {
- is: key,
- then: value,
- });
- });
- return schema;
-};
-
-export const USER_ADDRESS_PARAM = ':userAddress';
-export const SPECIAL_CONTEXT_PARAMS = [USER_ADDRESS_PARAM];
-
-class TimelockCondition extends Condition {
- public static readonly CONDITION_TYPE = 'timelock';
-
- defaults = {
- method: 'timelock',
- };
-
- public readonly schema = Joi.object({
- returnValueTest: this.makeReturnValueTest(),
- method: 'timelock',
- });
-}
-
-class RpcCondition extends Condition {
- public static readonly CONDITION_TYPE = 'rpc';
- public static readonly RPC_METHODS = ['eth_getBalance', 'balanceOf'];
- public static readonly PARAMETERS_PER_METHOD: Record = {
- eth_getBalance: ['address'],
- balanceOf: ['address'],
- };
- public static readonly CONTEXT_PARAMETERS_PER_METHOD: Record<
- string,
- string[]
- > = {
- eth_getBalance: [USER_ADDRESS_PARAM],
- balanceOf: [USER_ADDRESS_PARAM],
- };
-
- public readonly schema = Joi.object({
- chain: Joi.number()
- .valid(...Condition.SUPPORTED_CHAINS)
- .required(),
- method: Joi.string()
- .valid(...RpcCondition.RPC_METHODS)
- .required(),
- parameters: Joi.array().required(),
- returnValueTest: this.makeReturnValueTest(),
- });
-
- public getContextParameters = (): string[] => {
- const asObject = this.toObj();
-
- const method = asObject['method'] as string;
- const parameters = (asObject['parameters'] ?? []) as string[];
-
- const context = RpcCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
- const returnValueTest = asObject['returnValueTest'] as Record<
- string,
- string
- >;
-
- const maybeParams = [...(context ?? []), returnValueTest['value']];
- return parameters.filter((p) => maybeParams.includes(p));
- };
-}
-
-class EvmCondition extends Condition {
- public static readonly CONDITION_TYPE = 'evm';
- public static readonly STANDARD_CONTRACT_TYPES = [
- 'ERC20',
- 'ERC721',
- // 'ERC1155', // TODO(#131)
- ];
- public static readonly METHODS_PER_CONTRACT_TYPE: Record = {
- ERC20: ['balanceOf'],
- ERC721: ['balanceOf', 'ownerOf'],
- // ERC1155: ['balanceOf'], // TODO(#131)
- };
- public static readonly PARAMETERS_PER_METHOD: Record = {
- balanceOf: ['address'],
- ownerOf: ['tokenId'],
- };
- public static readonly CONTEXT_PARAMETERS_PER_METHOD: Record<
- string,
- string[]
- > = {
- balanceOf: [USER_ADDRESS_PARAM],
- ownerOf: [USER_ADDRESS_PARAM],
- };
-
- private makeMethod = () =>
- makeGuard(
- Joi.string(),
- EvmCondition.METHODS_PER_CONTRACT_TYPE,
- 'standardContractType'
- );
-
- public readonly schema = Joi.object({
- contractAddress: Joi.string()
- .pattern(new RegExp('^0x[a-fA-F0-9]{40}$'))
- .required(),
- chain: Joi.string()
- .valid(...Condition.SUPPORTED_CHAINS)
- .required(),
- standardContractType: Joi.string()
- .valid(...EvmCondition.STANDARD_CONTRACT_TYPES)
- .optional(),
- functionAbi: Joi.object().optional(),
- method: this.makeMethod().required(),
- parameters: Joi.array().required(),
- returnValueTest: this.makeReturnValueTest(),
- })
- // At most one of these keys needs to be present
- .xor('standardContractType', 'functionAbi');
-}
-
-class ERC721Ownership extends EvmCondition {
- readonly defaults = {
- method: 'ownerOf',
- parameters: [],
- standardContractType: 'ERC721',
- returnValueTest: {
- index: 0,
- comparator: '==',
- value: USER_ADDRESS_PARAM,
- },
- };
-}
-
-class ERC721Balance extends EvmCondition {
- readonly defaults = {
- method: 'balanceOf',
- parameters: [USER_ADDRESS_PARAM],
- standardContractType: 'ERC721',
- returnValueTest: {
- index: 0,
- comparator: '>',
- value: '0',
- },
- };
-}
-
-interface TypedSignature {
- signature: string;
- typedData: Eip712TypedData;
- address: string;
-}
-
-export type CustomContextParam = string | number | boolean;
-
-export class ConditionContext {
- private walletSignature?: Record;
-
- constructor(
- private readonly conditions: WASMConditions,
- private readonly web3Provider: ethers.providers.Web3Provider,
- public readonly customParameters: Record = {}
- ) {
- Object.keys(customParameters).forEach((key) => {
- if (SPECIAL_CONTEXT_PARAMS.includes(key)) {
- throw new Error(
- `Cannot use reserved parameter name ${key} as custom parameter`
- );
- }
- });
- }
-
- public async getOrCreateWalletSignature(): Promise {
- const address = await this.web3Provider.getSigner().getAddress();
- const storageKey = `wallet-signature-${address}`;
-
- // If we have a signature in localStorage, return it
- const isLocalStorage = typeof localStorage !== 'undefined';
- if (isLocalStorage) {
- const maybeSignature = localStorage.getItem(storageKey);
- if (maybeSignature) {
- return JSON.parse(maybeSignature);
- }
- }
-
- // If not, try returning from memory
- const maybeSignature = this.walletSignature?.[address];
- if (maybeSignature) {
- if (isLocalStorage) {
- localStorage.setItem(storageKey, maybeSignature);
- }
- return JSON.parse(maybeSignature);
- }
-
- // If at this point we didn't return, we need to create a new signature
- const typedSignature = await this.createWalletSignature();
-
- // Persist where you can
- if (isLocalStorage) {
- localStorage.setItem(storageKey, JSON.stringify(typedSignature));
- }
- if (!this.walletSignature) {
- this.walletSignature = {};
- }
- this.walletSignature[address] = JSON.stringify(typedSignature);
- return typedSignature;
- }
-
- private async createWalletSignature(): Promise {
- // Ensure freshness of the signature
- const { blockNumber, blockHash, chainId } = await this.getChainData();
- const address = await this.web3Provider.getSigner().getAddress();
- const signatureText = `I'm the owner of address ${address} as of block number ${blockNumber}`;
- const salt = ethersUtils.hexlify(ethersUtils.randomBytes(32));
-
- const typedData: Eip712TypedData = {
- types: {
- Wallet: [
- { name: 'address', type: 'address' },
- { name: 'signatureText', type: 'string' },
- { name: 'blockNumber', type: 'uint256' },
- { name: 'blockHash', type: 'bytes32' },
- ],
- },
- domain: {
- name: 'tDec',
- version: '1',
- chainId,
- salt,
- },
- message: {
- address,
- signatureText,
- blockNumber,
- blockHash,
- },
- };
- const signature = await this.web3Provider
- .getSigner()
- ._signTypedData(typedData.domain, typedData.types, typedData.message);
-
- const formattedTypedData: FormattedTypedData = {
- ...typedData,
- primaryType: 'Wallet',
- types: {
- ...typedData.types,
- EIP712Domain: [
- {
- name: 'name',
- type: 'string',
- },
- {
- name: 'version',
- type: 'string',
- },
- {
- name: 'chainId',
- type: 'uint256',
- },
- {
- name: 'salt',
- type: 'bytes32',
- },
- ],
- },
- };
- return { signature, typedData: formattedTypedData, address };
- }
-
- private async getChainData() {
- const blockNumber = await this.web3Provider.getBlockNumber();
- const blockHash = (await this.web3Provider.getBlock(blockNumber)).hash;
- const chainId = (await this.web3Provider.getNetwork()).chainId;
- return { blockNumber, blockHash, chainId };
- }
-
- public toJson = async (): Promise => {
- const payload: Record = {};
- if (this.conditions.toString().includes(USER_ADDRESS_PARAM)) {
- payload[USER_ADDRESS_PARAM] = await this.getOrCreateWalletSignature();
- }
-
- const conditions = JSON.parse(this.conditions.toString());
- conditions.forEach((cond: { parameters: string[] }) => {
- cond.parameters.forEach((key) => {
- if (
- !(key in this.customParameters) &&
- !SPECIAL_CONTEXT_PARAMS.includes(key)
- ) {
- throw new Error(`Missing custom context parameter ${key}`);
- }
- });
- });
-
- Object.keys(this.customParameters).forEach((key) => {
- payload[key] = this.customParameters[key];
- });
- return JSON.stringify(payload);
- };
-
- public withCustomParams = (
- params: Record
- ): ConditionContext => {
- return new ConditionContext(this.conditions, this.web3Provider, params);
- };
-}
-
-const OR = new Operator('or');
-const AND = new Operator('and');
-
-export const Conditions = {
- ERC721Ownership,
- ERC721Balance,
- EvmCondition,
- TimelockCondition,
- RpcCondition,
- Condition,
- OR,
- AND,
-};
diff --git a/src/sdk/strategy.ts b/src/sdk/strategy.ts
index 490e44d57..db713a304 100644
--- a/src/sdk/strategy.ts
+++ b/src/sdk/strategy.ts
@@ -10,7 +10,7 @@ import { Alice } from '../characters/alice';
import { Bob } from '../characters/bob';
import { Enrico } from '../characters/enrico';
import { tDecDecrypter } from '../characters/universal-bob';
-import { ConditionSet } from '../policies/conditions';
+import { ConditionSet } from '../conditions/condition-set';
import { EnactedPolicy, EnactedPolicyJSON } from '../policies/policy';
import { base64ToU8Receiver, u8ToBase64Replacer } from '../utils';
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index 3083a996e..141c8c2a0 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -6,10 +6,8 @@ import {
ConditionSet,
Operator,
} from '../../src';
-import {
- CustomContextParam,
- USER_ADDRESS_PARAM,
-} from '../../src/policies/conditions';
+import { CustomContextParam } from '../../src/conditions/condition-context';
+import { USER_ADDRESS_PARAM } from '../../src/conditions/conditions';
import { fakeWeb3Provider } from '../utils';
const TEST_CONTRACT_ADDR = '0xC36442b4a4522E871399CD717aBDD847Ab11FE88';
@@ -58,11 +56,7 @@ describe('condition set', () => {
const gnomePals = new Conditions.ERC721Balance({
contractAddress: TEST_CONTRACT_ADDR_2,
});
- const conditions = new ConditionSet([
- genuineUndead,
- Conditions.OR,
- gnomePals,
- ]);
+ const conditions = new ConditionSet([genuineUndead, Operator.AND, gnomePals]);
it('should validate', async () => {
expect(conditions.validate()).toEqual(true);
diff --git a/test/integration/pre.test.ts b/test/integration/pre.test.ts
index ef3565a42..106814b19 100644
--- a/test/integration/pre.test.ts
+++ b/test/integration/pre.test.ts
@@ -95,7 +95,7 @@ describe('proxy reencryption', () => {
});
const conditions = new ConditionSet([
genuineUndead,
- Operator.OR(),
+ Operator.OR,
gnomePals,
]);
From 04e87729bf611a60106e08fafe7888a562dbb853 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 10 May 2023 20:12:11 +0200
Subject: [PATCH 15/98] test: accept custom params in predefined methods
---
test/integration/conditions.test.ts | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index 3083a996e..8866bb972 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -291,7 +291,7 @@ describe('condition context', () => {
},
],
};
- const evmCondition = new Conditions.EvmCondition({
+ const evmConditionObj = {
chain: 5,
functionAbi: fakeFunctionAbi,
method: 'balanceOf',
@@ -302,7 +302,8 @@ describe('condition context', () => {
comparator: '==',
value: USER_ADDRESS_PARAM,
},
- });
+ };
+ const evmCondition = new Conditions.EvmCondition(evmConditionObj);
const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
const conditionSet = new ConditionSet([evmCondition]);
const conditionContext = new ConditionContext(
@@ -310,10 +311,10 @@ describe('condition context', () => {
web3Provider
);
const myCustomParam = ':customParam';
+ const customParams: Record = {};
+ customParams[myCustomParam] = 1234;
it('parses user-provided context parameters', async () => {
- const customParams: Record = {};
- customParams[myCustomParam] = 1234;
const asJson = await conditionContext
.withCustomParams(customParams)
.toJson();
@@ -336,6 +337,24 @@ describe('condition context', () => {
`Cannot use reserved parameter name ${USER_ADDRESS_PARAM} as custom parameter`
);
});
+
+ it('accepts custom parameters in predefined methods', async () => {
+ const customEvmCondition = new Conditions.EvmCondition({
+ ...evmConditionObj,
+ parameters: [myCustomParam],
+ });
+ const conditionSet = new ConditionSet([customEvmCondition]);
+ const conditionContext = new ConditionContext(
+ conditionSet.toWASMConditions(),
+ web3Provider
+ );
+
+ const asJson = await conditionContext
+ .withCustomParams(customParams)
+ .toJson();
+ expect(asJson).toBeDefined();
+ expect(asJson).toContain(myCustomParam);
+ });
});
});
From 6f4e6ffc30c383049db1c2f4cda540fbca828ef1 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 11 May 2023 09:04:47 +0200
Subject: [PATCH 16/98] refactor wallet auth into a seperate file
---
src/conditions/condition-context.ts | 114 ++------------------------
src/conditions/providers.ts | 119 ++++++++++++++++++++++++++++
2 files changed, 125 insertions(+), 108 deletions(-)
create mode 100644 src/conditions/providers.ts
diff --git a/src/conditions/condition-context.ts b/src/conditions/condition-context.ts
index 3e52e6f19..a2498d214 100644
--- a/src/conditions/condition-context.ts
+++ b/src/conditions/condition-context.ts
@@ -1,10 +1,10 @@
import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
-import { utils as ethersUtils } from 'ethers/lib/ethers';
-import { Eip712TypedData, FormattedTypedData } from '../web3';
+import { Eip712TypedData } from '../web3';
import { SPECIAL_CONTEXT_PARAMS, USER_ADDRESS_PARAM } from './conditions';
+import { WalletAuthenticationProvider } from './providers';
interface TypedSignature {
signature: string;
@@ -15,7 +15,7 @@ interface TypedSignature {
export type CustomContextParam = string | number | boolean;
export class ConditionContext {
- private walletSignature?: Record;
+ private readonly walletAuthProvider: WalletAuthenticationProvider;
constructor(
private readonly conditions: WASMConditions,
@@ -29,116 +29,14 @@ export class ConditionContext {
);
}
});
- }
-
- public async getOrCreateWalletSignature(): Promise {
- const address = await this.web3Provider.getSigner().getAddress();
- const storageKey = `wallet-signature-${address}`;
-
- // If we have a signature in localStorage, return it
- const isLocalStorage = typeof localStorage !== 'undefined';
- if (isLocalStorage) {
- const maybeSignature = localStorage.getItem(storageKey);
- if (maybeSignature) {
- return JSON.parse(maybeSignature);
- }
- }
-
- // If not, try returning from memory
- const maybeSignature = this.walletSignature?.[address];
- if (maybeSignature) {
- if (isLocalStorage) {
- localStorage.setItem(storageKey, maybeSignature);
- }
- return JSON.parse(maybeSignature);
- }
-
- // If at this point we didn't return, we need to create a new signature
- const typedSignature = await this.createWalletSignature();
-
- // Persist where you can
- if (isLocalStorage) {
- localStorage.setItem(storageKey, JSON.stringify(typedSignature));
- }
- if (!this.walletSignature) {
- this.walletSignature = {};
- }
- this.walletSignature[address] = JSON.stringify(typedSignature);
- return typedSignature;
- }
-
- private async createWalletSignature(): Promise {
- // Ensure freshness of the signature
- const { blockNumber, blockHash, chainId } = await this.getChainData();
- const address = await this.web3Provider.getSigner().getAddress();
- const signatureText = `I'm the owner of address ${address} as of block number ${blockNumber}`;
- const salt = ethersUtils.hexlify(ethersUtils.randomBytes(32));
-
- const typedData: Eip712TypedData = {
- types: {
- Wallet: [
- { name: 'address', type: 'address' },
- { name: 'signatureText', type: 'string' },
- { name: 'blockNumber', type: 'uint256' },
- { name: 'blockHash', type: 'bytes32' },
- ],
- },
- domain: {
- name: 'tDec',
- version: '1',
- chainId,
- salt,
- },
- message: {
- address,
- signatureText,
- blockNumber,
- blockHash,
- },
- };
- const signature = await this.web3Provider
- .getSigner()
- ._signTypedData(typedData.domain, typedData.types, typedData.message);
-
- const formattedTypedData: FormattedTypedData = {
- ...typedData,
- primaryType: 'Wallet',
- types: {
- ...typedData.types,
- EIP712Domain: [
- {
- name: 'name',
- type: 'string',
- },
- {
- name: 'version',
- type: 'string',
- },
- {
- name: 'chainId',
- type: 'uint256',
- },
- {
- name: 'salt',
- type: 'bytes32',
- },
- ],
- },
- };
- return { signature, typedData: formattedTypedData, address };
- }
-
- private async getChainData() {
- const blockNumber = await this.web3Provider.getBlockNumber();
- const blockHash = (await this.web3Provider.getBlock(blockNumber)).hash;
- const chainId = (await this.web3Provider.getNetwork()).chainId;
- return { blockNumber, blockHash, chainId };
+ this.walletAuthProvider = new WalletAuthenticationProvider(web3Provider);
}
public toJson = async (): Promise => {
const payload: Record = {};
if (this.conditions.toString().includes(USER_ADDRESS_PARAM)) {
- payload[USER_ADDRESS_PARAM] = await this.getOrCreateWalletSignature();
+ payload[USER_ADDRESS_PARAM] =
+ await this.walletAuthProvider.getOrCreateWalletSignature();
}
const conditions = JSON.parse(this.conditions.toString());
diff --git a/src/conditions/providers.ts b/src/conditions/providers.ts
new file mode 100644
index 000000000..d7b72210f
--- /dev/null
+++ b/src/conditions/providers.ts
@@ -0,0 +1,119 @@
+import { ethers } from 'ethers';
+import { utils as ethersUtils } from 'ethers/lib/ethers';
+
+import { Eip712TypedData, FormattedTypedData } from '../web3';
+
+interface TypedSignature {
+ signature: string;
+ typedData: Eip712TypedData;
+ address: string;
+}
+export class WalletAuthenticationProvider {
+ private walletSignature?: Record;
+
+ constructor(private readonly web3Provider: ethers.providers.Web3Provider) {}
+
+ public async getOrCreateWalletSignature(): Promise {
+ const address = await this.web3Provider.getSigner().getAddress();
+ const storageKey = `wallet-signature-${address}`;
+
+ // If we have a signature in localStorage, return it
+ const isLocalStorage = typeof localStorage !== 'undefined';
+ if (isLocalStorage) {
+ const maybeSignature = localStorage.getItem(storageKey);
+ if (maybeSignature) {
+ return JSON.parse(maybeSignature);
+ }
+ }
+
+ // If not, try returning from memory
+ const maybeSignature = this.walletSignature?.[address];
+ if (maybeSignature) {
+ if (isLocalStorage) {
+ localStorage.setItem(storageKey, maybeSignature);
+ }
+ return JSON.parse(maybeSignature);
+ }
+
+ // If at this point we didn't return, we need to create a new signature
+ const typedSignature = await this.createWalletSignature();
+
+ // Persist where you can
+ if (isLocalStorage) {
+ localStorage.setItem(storageKey, JSON.stringify(typedSignature));
+ }
+ if (!this.walletSignature) {
+ this.walletSignature = {};
+ }
+ this.walletSignature[address] = JSON.stringify(typedSignature);
+ return typedSignature;
+ }
+
+ private async createWalletSignature(): Promise {
+ // Ensure freshness of the signature
+ const { blockNumber, blockHash, chainId } = await this.getChainData();
+ const address = await this.web3Provider.getSigner().getAddress();
+ const signatureText = `I'm the owner of address ${address} as of block number ${blockNumber}`;
+ const salt = ethersUtils.hexlify(ethersUtils.randomBytes(32));
+
+ const typedData: Eip712TypedData = {
+ types: {
+ Wallet: [
+ { name: 'address', type: 'address' },
+ { name: 'signatureText', type: 'string' },
+ { name: 'blockNumber', type: 'uint256' },
+ { name: 'blockHash', type: 'bytes32' },
+ ],
+ },
+ domain: {
+ name: 'tDec',
+ version: '1',
+ chainId,
+ salt,
+ },
+ message: {
+ address,
+ signatureText,
+ blockNumber,
+ blockHash,
+ },
+ };
+ const signature = await this.web3Provider
+ .getSigner()
+ ._signTypedData(typedData.domain, typedData.types, typedData.message);
+
+ const formattedTypedData: FormattedTypedData = {
+ ...typedData,
+ primaryType: 'Wallet',
+ types: {
+ ...typedData.types,
+ EIP712Domain: [
+ {
+ name: 'name',
+ type: 'string',
+ },
+ {
+ name: 'version',
+ type: 'string',
+ },
+ {
+ name: 'chainId',
+ type: 'uint256',
+ },
+ {
+ name: 'salt',
+ type: 'bytes32',
+ },
+ ],
+ },
+ };
+ return { signature, typedData: formattedTypedData, address };
+ }
+
+ private async getChainData() {
+ const blockNumber = await this.web3Provider.getBlockNumber();
+ const blockHash = (await this.web3Provider.getBlock(blockNumber)).hash;
+ const chainId = (await this.web3Provider.getNetwork()).chainId;
+ return { blockNumber, blockHash, chainId };
+ }
+}
From 055a17f590c6583be1477b76def0442863306767 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 11 May 2023 09:10:47 +0200
Subject: [PATCH 17/98] refactor supported chains out of condition class
---
src/agents/contracts.ts | 8 +++++++-
src/conditions/conditions.ts | 23 ++++++++++++-----------
src/types.ts | 1 +
3 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/src/agents/contracts.ts b/src/agents/contracts.ts
index 92c0b12f1..19b6059d3 100644
--- a/src/agents/contracts.ts
+++ b/src/agents/contracts.ts
@@ -20,15 +20,21 @@ const GOERLI: Contracts = {
COORDINATOR: '0x2cf19429168a0943992D8e7dE534E9b802C687B6',
};
+const MAINNET: Contracts = {
+ SUBSCRIPTION_MANAGER: undefined,
+ COORDINATOR: 'undefined',
+};
+
const CONTRACTS: { readonly [key in ChainId]: Contracts } = {
[ChainId.POLYGON]: POLYGON,
[ChainId.MUMBAI]: MUMBAI,
[ChainId.GOERLI]: GOERLI,
+ [ChainId.MAINNET]: MAINNET,
};
export const getContract = (
chainId: number,
- contract: keyof Contracts
+ contract: keyof Contracts,
): ChecksumAddress => {
if (!Object.values(ChainId).includes(chainId)) {
throw new Error(`No contracts found for chainId: ${chainId}`);
diff --git a/src/conditions/conditions.ts b/src/conditions/conditions.ts
index 1dcf5765d..b591f5c8d 100644
--- a/src/conditions/conditions.ts
+++ b/src/conditions/conditions.ts
@@ -1,7 +1,15 @@
import Joi, { ValidationError } from 'joi';
+import { ChainId } from '../types';
+
+export const SUPPORTED_CHAINS = [
+ ChainId.POLYGON,
+ ChainId.MUMBAI,
+ ChainId.GOERLI,
+ ChainId.MAINNET,
+]
export class Condition {
- public static readonly COMPARATOR_OPERATORS = [
+ public static readonly COMPARATORS = [
'==',
'>',
'<',
@@ -10,13 +18,6 @@ export class Condition {
'!=',
];
- public static readonly SUPPORTED_CHAINS = [
- 1, // ethereum/mainnet
- 5, // ethereum/goerli
- 137, // polygon/mainnet
- 80001, // polygon/mumbai
- ];
-
public readonly schema = Joi.object();
public readonly defaults = {};
private validationError?: ValidationError;
@@ -31,7 +32,7 @@ export class Condition {
return Joi.object({
index: Joi.number().optional(),
comparator: Joi.string()
- .valid(...Condition.COMPARATOR_OPERATORS)
+ .valid(...Condition.COMPARATORS)
.required(),
value: Joi.alternatives(Joi.string(), Joi.number()).required(),
});
@@ -136,7 +137,7 @@ class RpcCondition extends Condition {
public readonly schema = Joi.object({
chain: Joi.number()
- .valid(...Condition.SUPPORTED_CHAINS)
+ .valid(...SUPPORTED_CHAINS)
.required(),
method: Joi.string()
.valid(...RpcCondition.RPC_METHODS)
@@ -198,7 +199,7 @@ class EvmCondition extends Condition {
.pattern(new RegExp('^0x[a-fA-F0-9]{40}$'))
.required(),
chain: Joi.string()
- .valid(...Condition.SUPPORTED_CHAINS)
+ .valid(...SUPPORTED_CHAINS)
.required(),
standardContractType: Joi.string()
.valid(...EvmCondition.STANDARD_CONTRACT_TYPES)
diff --git a/src/types.ts b/src/types.ts
index 5fedf560e..2440dcc53 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -6,4 +6,5 @@ export enum ChainId {
POLYGON = 137,
MUMBAI = 80001,
GOERLI = 5,
+ MAINNET = 1,
}
From b02b0632652801facd1d7a94684717bfd4efae31 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 11 May 2023 09:32:28 +0200
Subject: [PATCH 18/98] replace tdec domain name in eip sig with cbd
---
src/conditions/providers.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/conditions/providers.ts b/src/conditions/providers.ts
index d7b72210f..907ba87ec 100644
--- a/src/conditions/providers.ts
+++ b/src/conditions/providers.ts
@@ -66,7 +66,7 @@ export class WalletAuthenticationProvider {
],
},
domain: {
- name: 'tDec',
+ name: 'cbd',
version: '1',
chainId,
salt,
From 5415ad8095c8b8a58776089bf750e77ed2acdfb3 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 11 May 2023 09:33:07 +0200
Subject: [PATCH 19/98] fix prettier
---
src/agents/contracts.ts | 2 +-
src/conditions/conditions.ts | 11 ++---------
2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/src/agents/contracts.ts b/src/agents/contracts.ts
index 19b6059d3..1af9f6aba 100644
--- a/src/agents/contracts.ts
+++ b/src/agents/contracts.ts
@@ -34,7 +34,7 @@ const CONTRACTS: { readonly [key in ChainId]: Contracts } = {
export const getContract = (
chainId: number,
- contract: keyof Contracts,
+ contract: keyof Contracts
): ChecksumAddress => {
if (!Object.values(ChainId).includes(chainId)) {
throw new Error(`No contracts found for chainId: ${chainId}`);
diff --git a/src/conditions/conditions.ts b/src/conditions/conditions.ts
index b591f5c8d..39e226688 100644
--- a/src/conditions/conditions.ts
+++ b/src/conditions/conditions.ts
@@ -7,16 +7,9 @@ export const SUPPORTED_CHAINS = [
ChainId.MUMBAI,
ChainId.GOERLI,
ChainId.MAINNET,
-]
+];
export class Condition {
- public static readonly COMPARATORS = [
- '==',
- '>',
- '<',
- '>=',
- '<=',
- '!=',
- ];
+ public static readonly COMPARATORS = ['==', '>', '<', '>=', '<=', '!='];
public readonly schema = Joi.object();
public readonly defaults = {};
From 63fabdb813b542fa227e168b4e51ef003ea7ba6c Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 11 May 2023 09:35:27 +0200
Subject: [PATCH 20/98] fix tests
---
src/conditions/conditions.ts | 4 ++--
src/config.ts | 4 ++++
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/src/conditions/conditions.ts b/src/conditions/conditions.ts
index 39e226688..1985723d3 100644
--- a/src/conditions/conditions.ts
+++ b/src/conditions/conditions.ts
@@ -3,10 +3,10 @@ import Joi, { ValidationError } from 'joi';
import { ChainId } from '../types';
export const SUPPORTED_CHAINS = [
+ ChainId.MAINNET,
+ ChainId.GOERLI,
ChainId.POLYGON,
ChainId.MUMBAI,
- ChainId.GOERLI,
- ChainId.MAINNET,
];
export class Condition {
public static readonly COMPARATORS = ['==', '>', '<', '>=', '<=', '!='];
diff --git a/src/config.ts b/src/config.ts
index 99bfb02cf..7835c14f1 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -15,6 +15,10 @@ const CONFIGS: { readonly [key in ChainId]: Configuration } = {
// TODO: Confirm this is correct
porterUri: 'https://porter-tapir.nucypher.community',
},
+ [ChainId.MAINNET]: {
+ // TODO: Confirm this is correct
+ porterUri: 'https://porter.nucypher.community',
+ },
};
export const defaultConfiguration = (chainId: number): Configuration => {
From 85ff684efe3e4a9b32d628e65606770459d96a7c Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 11 May 2023 11:48:55 +0200
Subject: [PATCH 21/98] feat!: refactor conditions into a module
---
src/conditions/base/evm.ts | 70 ++++++++
src/conditions/base/index.ts | 3 +
src/conditions/base/rpc.ts | 49 ++++++
src/conditions/base/timelock.ts | 16 ++
src/conditions/condition-context.ts | 4 +-
src/conditions/condition-set.ts | 2 +-
src/conditions/condition.ts | 75 +++++++++
src/conditions/conditions.ts | 242 ----------------------------
src/conditions/const.ts | 10 ++
src/conditions/index.ts | 9 ++
src/conditions/predefined/erc721.ts | 28 ++++
src/conditions/predefined/index.ts | 1 +
src/index.ts | 33 ++--
test/docs/cbd.test.ts | 22 +--
test/integration/conditions.test.ts | 68 ++++----
test/integration/enrico.test.ts | 14 +-
test/integration/pre.test.ts | 23 ++-
test/unit/strategy.test.ts | 10 +-
tsconfig.json | 1 +
19 files changed, 362 insertions(+), 318 deletions(-)
create mode 100644 src/conditions/base/evm.ts
create mode 100644 src/conditions/base/index.ts
create mode 100644 src/conditions/base/rpc.ts
create mode 100644 src/conditions/base/timelock.ts
create mode 100644 src/conditions/condition.ts
delete mode 100644 src/conditions/conditions.ts
create mode 100644 src/conditions/const.ts
create mode 100644 src/conditions/index.ts
create mode 100644 src/conditions/predefined/erc721.ts
create mode 100644 src/conditions/predefined/index.ts
diff --git a/src/conditions/base/evm.ts b/src/conditions/base/evm.ts
new file mode 100644
index 000000000..ef6aa6bc3
--- /dev/null
+++ b/src/conditions/base/evm.ts
@@ -0,0 +1,70 @@
+import Joi from 'joi';
+
+import { Condition } from '../condition';
+import { SUPPORTED_CHAINS, USER_ADDRESS_PARAM } from '../const';
+
+// A helper method for making complex Joi types
+// It says "allow these `types` when `parent` value is given"
+const makeGuard = (
+ schema: Joi.StringSchema | Joi.ArraySchema,
+ types: Record,
+ parent: string
+) => {
+ Object.entries(types).forEach(([key, value]) => {
+ schema = schema.when(parent, {
+ is: key,
+ then: value,
+ });
+ });
+ return schema;
+};
+
+export class EvmCondition extends Condition {
+ public static readonly CONDITION_TYPE = 'evm';
+ public static readonly STANDARD_CONTRACT_TYPES = [
+ 'ERC20',
+ 'ERC721',
+ // 'ERC1155', // TODO(#131)
+ ];
+ public static readonly METHODS_PER_CONTRACT_TYPE: Record = {
+ ERC20: ['balanceOf'],
+ ERC721: ['balanceOf', 'ownerOf'],
+ // ERC1155: ['balanceOf'], // TODO(#131)
+ };
+ public static readonly PARAMETERS_PER_METHOD: Record = {
+ balanceOf: ['address'],
+ ownerOf: ['tokenId'],
+ };
+ public static readonly CONTEXT_PARAMETERS_PER_METHOD: Record<
+ string,
+ string[]
+ > = {
+ balanceOf: [USER_ADDRESS_PARAM],
+ ownerOf: [USER_ADDRESS_PARAM],
+ };
+
+ private makeMethod = () =>
+ makeGuard(
+ Joi.string(),
+ EvmCondition.METHODS_PER_CONTRACT_TYPE,
+ 'standardContractType'
+ );
+
+ public readonly schema = Joi.object({
+ contractAddress: Joi.string()
+ .pattern(new RegExp('^0x[a-fA-F0-9]{40}$'))
+ .required(),
+ chain: Joi.string()
+ .valid(...SUPPORTED_CHAINS)
+ .required(),
+ standardContractType: Joi.string()
+ .valid(...EvmCondition.STANDARD_CONTRACT_TYPES)
+ .optional(),
+ functionAbi: Joi.object().optional(),
+ method: this.makeMethod().required(),
+ parameters: Joi.array().required(),
+ returnValueTest: this.makeReturnValueTest(),
+ })
+ // At most one of these keys needs to be present
+ .xor('standardContractType', 'functionAbi');
+}
diff --git a/src/conditions/base/index.ts b/src/conditions/base/index.ts
new file mode 100644
index 000000000..0942d8b6a
--- /dev/null
+++ b/src/conditions/base/index.ts
@@ -0,0 +1,3 @@
+export { EvmCondition } from './evm';
+export { RpcCondition } from './rpc';
+export { TimelockCondition } from './timelock';
diff --git a/src/conditions/base/rpc.ts b/src/conditions/base/rpc.ts
new file mode 100644
index 000000000..6aeffccf7
--- /dev/null
+++ b/src/conditions/base/rpc.ts
@@ -0,0 +1,49 @@
+import Joi from 'joi';
+
+import { Condition } from '../condition';
+import { SUPPORTED_CHAINS, USER_ADDRESS_PARAM } from '../const';
+
+export const RpcConditionConfig = {
+ CONDITION_TYPE: 'rpc',
+ RPC_METHODS: ['eth_getBalance', 'balanceOf'],
+ PARAMETERS_PER_METHOD: {
+ eth_getBalance: ['address'],
+ balanceOf: ['address'],
+ },
+ CONTEXT_PARAMETERS_PER_METHOD: {
+ eth_getBalance: [USER_ADDRESS_PARAM],
+ balanceOf: [USER_ADDRESS_PARAM],
+ },
+};
+
+export class RpcCondition extends Condition {
+ public readonly schema = Joi.object({
+ chain: Joi.number()
+ .valid(...SUPPORTED_CHAINS)
+ .required(),
+ method: Joi.string()
+ .valid(...RpcConditionConfig.RPC_METHODS)
+ .required(),
+ parameters: Joi.array().required(),
+ returnValueTest: this.makeReturnValueTest(),
+ });
+
+ public getContextParameters = (): string[] => {
+ const asObject = this.toObj();
+
+ const method = asObject['method'] as string;
+ const parameters = (asObject['parameters'] ?? []) as string[];
+
+ const context: string[] =
+ RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[
+ method as keyof typeof RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD
+ ];
+ const returnValueTest = asObject['returnValueTest'] as Record<
+ string,
+ string
+ >;
+
+ const maybeParams = [...(context ?? []), returnValueTest['value']];
+ return parameters.filter((p) => maybeParams.includes(p));
+ };
+}
diff --git a/src/conditions/base/timelock.ts b/src/conditions/base/timelock.ts
new file mode 100644
index 000000000..a42e7431e
--- /dev/null
+++ b/src/conditions/base/timelock.ts
@@ -0,0 +1,16 @@
+import Joi from 'joi';
+
+import { Condition } from '../condition';
+
+export class TimelockCondition extends Condition {
+ public static readonly CONDITION_TYPE = 'timelock';
+
+ defaults = {
+ method: 'timelock',
+ };
+
+ public readonly schema = Joi.object({
+ returnValueTest: this.makeReturnValueTest(),
+ method: 'timelock',
+ });
+}
diff --git a/src/conditions/condition-context.ts b/src/conditions/condition-context.ts
index a2498d214..c63b3dc8a 100644
--- a/src/conditions/condition-context.ts
+++ b/src/conditions/condition-context.ts
@@ -3,7 +3,7 @@ import { ethers } from 'ethers';
import { Eip712TypedData } from '../web3';
-import { SPECIAL_CONTEXT_PARAMS, USER_ADDRESS_PARAM } from './conditions';
+import { USER_ADDRESS_PARAM } from './const';
import { WalletAuthenticationProvider } from './providers';
interface TypedSignature {
@@ -14,6 +14,8 @@ interface TypedSignature {
export type CustomContextParam = string | number | boolean;
+const SPECIAL_CONTEXT_PARAMS = [USER_ADDRESS_PARAM];
+
export class ConditionContext {
private readonly walletAuthProvider: WalletAuthenticationProvider;
diff --git a/src/conditions/condition-set.ts b/src/conditions/condition-set.ts
index f8d21e966..8165f30a8 100644
--- a/src/conditions/condition-set.ts
+++ b/src/conditions/condition-set.ts
@@ -1,8 +1,8 @@
import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
+import { Condition } from './condition';
import { ConditionContext } from './condition-context';
-import { Condition } from './conditions';
import { Operator } from './operator';
export class ConditionSet {
diff --git a/src/conditions/condition.ts b/src/conditions/condition.ts
new file mode 100644
index 000000000..59b0c962c
--- /dev/null
+++ b/src/conditions/condition.ts
@@ -0,0 +1,75 @@
+import Joi, { ValidationError } from 'joi';
+
+export class Condition {
+ public static readonly COMPARATORS = ['==', '>', '<', '>=', '<=', '!='];
+
+ public readonly schema = Joi.object();
+ public readonly defaults = {};
+ private validationError?: ValidationError;
+
+ constructor(private readonly value: Record = {}) {}
+
+ public get error(): string | undefined {
+ return this.validationError?.message;
+ }
+
+ protected makeReturnValueTest() {
+ return Joi.object({
+ index: Joi.number().optional(),
+ comparator: Joi.string()
+ .valid(...Condition.COMPARATORS)
+ .required(),
+ value: Joi.alternatives(Joi.string(), Joi.number()).required(),
+ });
+ }
+
+ public toObj(): Record {
+ const { error, value } = this.validate();
+ if (error) {
+ throw Error(error.message);
+ }
+ return value;
+ }
+
+ public static fromObj(obj: Record) {
+ return new Condition(obj);
+ }
+
+ public validate(data: Record = {}) {
+ const newValue = Object.assign(this.defaults, this.value, data);
+ return this.schema.validate(newValue);
+ }
+
+ protected getContextParametersConfig(): Record {
+ // Empty configuration object by default, to be implemented by subclasses
+ return {};
+ }
+
+ public getContextParameters(): string[] {
+ const asObject = this.toObj();
+ let paramsToCheck: string[] = [];
+
+ const method = asObject['method'] as string;
+ if (method) {
+ const contextParams = this.getContextParametersConfig()[method];
+ paramsToCheck = [...(contextParams ?? [])];
+ }
+
+ const returnValueTest = asObject['returnValueTest'] as Record<
+ string,
+ string
+ >;
+ if (returnValueTest) {
+ paramsToCheck.push(returnValueTest['value']);
+ }
+
+ paramsToCheck = [
+ ...paramsToCheck,
+ ...((asObject['parameters'] as string[]) ?? []),
+ ];
+ const withoutDuplicates = new Set(
+ paramsToCheck.filter((p) => paramsToCheck.includes(p))
+ );
+ return [...withoutDuplicates];
+ }
+}
diff --git a/src/conditions/conditions.ts b/src/conditions/conditions.ts
deleted file mode 100644
index 1985723d3..000000000
--- a/src/conditions/conditions.ts
+++ /dev/null
@@ -1,242 +0,0 @@
-import Joi, { ValidationError } from 'joi';
-
-import { ChainId } from '../types';
-
-export const SUPPORTED_CHAINS = [
- ChainId.MAINNET,
- ChainId.GOERLI,
- ChainId.POLYGON,
- ChainId.MUMBAI,
-];
-export class Condition {
- public static readonly COMPARATORS = ['==', '>', '<', '>=', '<=', '!='];
-
- public readonly schema = Joi.object();
- public readonly defaults = {};
- private validationError?: ValidationError;
-
- constructor(private readonly value: Record = {}) {}
-
- public get error(): string | undefined {
- return this.validationError?.message;
- }
-
- protected makeReturnValueTest() {
- return Joi.object({
- index: Joi.number().optional(),
- comparator: Joi.string()
- .valid(...Condition.COMPARATORS)
- .required(),
- value: Joi.alternatives(Joi.string(), Joi.number()).required(),
- });
- }
-
- public toObj(): Record {
- const { error, value } = this.validate();
- if (error) {
- throw Error(error.message);
- }
- return value;
- }
-
- public static fromObj(obj: Record) {
- return new Condition(obj);
- }
-
- public validate(data: Record = {}) {
- const newValue = Object.assign(this.defaults, this.value, data);
- return this.schema.validate(newValue);
- }
-
- public getContextParameters(): string[] {
- // Check all the places where context parameters may be hiding
- const asObject = this.toObj();
- let paramsToCheck: string[] = [];
-
- // They may be hiding in the method parameters
- const method = asObject['method'] as string;
- if (method) {
- const contextParams = RpcCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
- paramsToCheck = [...(contextParams ?? [])];
- }
-
- // Or in the ReturnValue test
- const returnValueTest = asObject['returnValueTest'] as Record<
- string,
- string
- >;
- if (returnValueTest) {
- paramsToCheck.push(returnValueTest['value']);
- }
-
- // Merge & deduplicate found context parameters
- paramsToCheck = [
- ...paramsToCheck,
- ...((asObject['parameters'] as string[]) ?? []),
- ];
- const withoutDuplicates = new Set(
- paramsToCheck.filter((p) => paramsToCheck.includes(p))
- );
- return [...withoutDuplicates];
- }
-}
-
-// A helper method for making complex Joi types
-// It says "allow these `types` when `parent` value is given"
-const makeGuard = (
- schema: Joi.StringSchema | Joi.ArraySchema,
- types: Record,
- parent: string
-) => {
- Object.entries(types).forEach(([key, value]) => {
- schema = schema.when(parent, {
- is: key,
- then: value,
- });
- });
- return schema;
-};
-
-export const USER_ADDRESS_PARAM = ':userAddress';
-export const SPECIAL_CONTEXT_PARAMS = [USER_ADDRESS_PARAM];
-
-class TimelockCondition extends Condition {
- public static readonly CONDITION_TYPE = 'timelock';
-
- defaults = {
- method: 'timelock',
- };
-
- public readonly schema = Joi.object({
- returnValueTest: this.makeReturnValueTest(),
- method: 'timelock',
- });
-}
-
-class RpcCondition extends Condition {
- public static readonly CONDITION_TYPE = 'rpc';
- public static readonly RPC_METHODS = ['eth_getBalance', 'balanceOf'];
- public static readonly PARAMETERS_PER_METHOD: Record = {
- eth_getBalance: ['address'],
- balanceOf: ['address'],
- };
- public static readonly CONTEXT_PARAMETERS_PER_METHOD: Record<
- string,
- string[]
- > = {
- eth_getBalance: [USER_ADDRESS_PARAM],
- balanceOf: [USER_ADDRESS_PARAM],
- };
-
- public readonly schema = Joi.object({
- chain: Joi.number()
- .valid(...SUPPORTED_CHAINS)
- .required(),
- method: Joi.string()
- .valid(...RpcCondition.RPC_METHODS)
- .required(),
- parameters: Joi.array().required(),
- returnValueTest: this.makeReturnValueTest(),
- });
-
- public getContextParameters = (): string[] => {
- const asObject = this.toObj();
-
- const method = asObject['method'] as string;
- const parameters = (asObject['parameters'] ?? []) as string[];
-
- const context = RpcCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
- const returnValueTest = asObject['returnValueTest'] as Record<
- string,
- string
- >;
-
- const maybeParams = [...(context ?? []), returnValueTest['value']];
- return parameters.filter((p) => maybeParams.includes(p));
- };
-}
-
-class EvmCondition extends Condition {
- public static readonly CONDITION_TYPE = 'evm';
- public static readonly STANDARD_CONTRACT_TYPES = [
- 'ERC20',
- 'ERC721',
- // 'ERC1155', // TODO(#131)
- ];
- public static readonly METHODS_PER_CONTRACT_TYPE: Record = {
- ERC20: ['balanceOf'],
- ERC721: ['balanceOf', 'ownerOf'],
- // ERC1155: ['balanceOf'], // TODO(#131)
- };
- public static readonly PARAMETERS_PER_METHOD: Record = {
- balanceOf: ['address'],
- ownerOf: ['tokenId'],
- };
- public static readonly CONTEXT_PARAMETERS_PER_METHOD: Record<
- string,
- string[]
- > = {
- balanceOf: [USER_ADDRESS_PARAM],
- ownerOf: [USER_ADDRESS_PARAM],
- };
-
- private makeMethod = () =>
- makeGuard(
- Joi.string(),
- EvmCondition.METHODS_PER_CONTRACT_TYPE,
- 'standardContractType'
- );
-
- public readonly schema = Joi.object({
- contractAddress: Joi.string()
- .pattern(new RegExp('^0x[a-fA-F0-9]{40}$'))
- .required(),
- chain: Joi.string()
- .valid(...SUPPORTED_CHAINS)
- .required(),
- standardContractType: Joi.string()
- .valid(...EvmCondition.STANDARD_CONTRACT_TYPES)
- .optional(),
- functionAbi: Joi.object().optional(),
- method: this.makeMethod().required(),
- parameters: Joi.array().required(),
- returnValueTest: this.makeReturnValueTest(),
- })
- // At most one of these keys needs to be present
- .xor('standardContractType', 'functionAbi');
-}
-
-class ERC721Ownership extends EvmCondition {
- readonly defaults = {
- method: 'ownerOf',
- parameters: [],
- standardContractType: 'ERC721',
- returnValueTest: {
- index: 0,
- comparator: '==',
- value: USER_ADDRESS_PARAM,
- },
- };
-}
-
-class ERC721Balance extends EvmCondition {
- readonly defaults = {
- method: 'balanceOf',
- parameters: [USER_ADDRESS_PARAM],
- standardContractType: 'ERC721',
- returnValueTest: {
- index: 0,
- comparator: '>',
- value: '0',
- },
- };
-}
-
-export const Conditions = {
- ERC721Ownership,
- ERC721Balance,
- EvmCondition,
- TimelockCondition,
- RpcCondition,
- Condition,
-};
diff --git a/src/conditions/const.ts b/src/conditions/const.ts
new file mode 100644
index 000000000..f0d3f2ced
--- /dev/null
+++ b/src/conditions/const.ts
@@ -0,0 +1,10 @@
+import { ChainId } from '../types';
+
+export const SUPPORTED_CHAINS = [
+ ChainId.MAINNET,
+ ChainId.GOERLI,
+ ChainId.POLYGON,
+ ChainId.MUMBAI,
+];
+
+export const USER_ADDRESS_PARAM = ':userAddress';
diff --git a/src/conditions/index.ts b/src/conditions/index.ts
new file mode 100644
index 000000000..2e3759a57
--- /dev/null
+++ b/src/conditions/index.ts
@@ -0,0 +1,9 @@
+import * as base from './base';
+import * as predefined from './predefined';
+
+export { predefined, base };
+export { Condition } from './condition';
+export { ConditionSet } from './condition-set';
+export { Operator } from './operator';
+export type { CustomContextParam } from './condition-context';
+export { ConditionContext } from './condition-context';
diff --git a/src/conditions/predefined/erc721.ts b/src/conditions/predefined/erc721.ts
new file mode 100644
index 000000000..211a0b11b
--- /dev/null
+++ b/src/conditions/predefined/erc721.ts
@@ -0,0 +1,28 @@
+import { EvmCondition } from '../base';
+import { USER_ADDRESS_PARAM } from '../const';
+
+export class ERC721Ownership extends EvmCondition {
+ readonly defaults = {
+ method: 'ownerOf',
+ parameters: [],
+ standardContractType: 'ERC721',
+ returnValueTest: {
+ index: 0,
+ comparator: '==',
+ value: USER_ADDRESS_PARAM,
+ },
+ };
+}
+
+export class ERC721Balance extends EvmCondition {
+ readonly defaults = {
+ method: 'balanceOf',
+ parameters: [USER_ADDRESS_PARAM],
+ standardContractType: 'ERC721',
+ returnValueTest: {
+ index: 0,
+ comparator: '>',
+ value: '0',
+ },
+ };
+}
diff --git a/src/conditions/predefined/index.ts b/src/conditions/predefined/index.ts
new file mode 100644
index 000000000..2c08b2da4
--- /dev/null
+++ b/src/conditions/predefined/index.ts
@@ -0,0 +1 @@
+export { ERC721Balance, ERC721Ownership } from './erc721';
diff --git a/src/index.ts b/src/index.ts
index 83dffc869..b187a9e8d 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,28 +1,39 @@
+// Characters
export { Alice } from './characters/alice';
export { Bob, RemoteBob } from './characters/bob';
export { Enrico } from './characters/enrico';
export { tDecDecrypter } from './characters/universal-bob';
-export {
+export { Porter } from './characters/porter';
+
+// Policies
+export type {
BlockchainPolicyParameters,
EnactedPolicy,
- PreEnactedPolicy,
} from './policies/policy';
-export { Porter } from './characters/porter';
+export { PreEnactedPolicy } from './policies/policy';
+
+// Keyring
export { Keyring } from './keyring';
-export { Configuration, defaultConfiguration } from './config';
+
+// Configuration
+export type { Configuration } from './config';
+export { defaultConfiguration } from './config';
+
+// Kits
export { RevocationKit } from './kits/revocation';
export { PolicyMessageKit } from './kits/message';
-export { Conditions, Condition } from './conditions/conditions';
-export { Operator } from './conditions/operator';
-export { ConditionSet } from './conditions/condition-set';
-export {
- ConditionContext,
- CustomContextParam,
-} from './conditions/condition-context';
+// Conditions
+import type { CustomContextParam } from './conditions';
+import * as conditions from './conditions';
+// TODO: Not sure how to re-export this type from the conditions module
+export { conditions, CustomContextParam };
+
+// SDK
export { Cohort } from './sdk/cohort';
export { DeployedStrategy, RevokedStrategy, Strategy } from './sdk/strategy';
+// Re-exports
export {
PublicKey,
SecretKey,
diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts
index 630091eb1..a938959e3 100644
--- a/test/docs/cbd.test.ts
+++ b/test/docs/cbd.test.ts
@@ -1,13 +1,7 @@
import { MessageKit, VerifiedKeyFrag } from '@nucypher/nucypher-core';
import { providers } from 'ethers';
-import {
- Cohort,
- Conditions,
- ConditionSet,
- SecretKey,
- Strategy,
-} from '../../src';
+import { Cohort, conditions, SecretKey, Strategy } from '../../src';
import { Ursula } from '../../src/characters/porter';
import { toBytes } from '../../src/utils';
import {
@@ -22,6 +16,12 @@ import {
mockRetrieveCFragsRequest,
} from '../utils';
+const {
+ predefined: { ERC721Ownership },
+ ConditionSet,
+ Condition,
+} = conditions;
+
describe('Get Started (CBD PoC)', () => {
function mockRetrieveAndDecrypt(
makeTreasureMapSpy: jest.SpyInstance,
@@ -67,8 +67,8 @@ describe('Get Started (CBD PoC)', () => {
};
const newCohort = await Cohort.create(config);
- // 3. Specify default Conditions
- const NFTOwnership = new Conditions.ERC721Ownership({
+ // 3. Specify default predefined
+ const NFTOwnership = new ERC721Ownership({
contractAddress: '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D',
chain: 5, // Tapir network uses Görli testnet
parameters: [5954],
@@ -88,7 +88,7 @@ describe('Get Started (CBD PoC)', () => {
const web3Provider = new providers.Web3Provider(MMprovider, mumbai);
const newDeployed = await newStrategy.deploy('test', web3Provider);
- // 5. Encrypt the plaintext & update Conditions
+ // 5. Encrypt the plaintext & update predefined
const NFTBalanceConfig = {
contractAddress: '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D',
standardContractType: 'ERC721',
@@ -100,7 +100,7 @@ describe('Get Started (CBD PoC)', () => {
value: 3,
},
};
- const NFTBalance = new Conditions.Condition(NFTBalanceConfig);
+ const NFTBalance = new Condition(NFTBalanceConfig);
const encrypter = newDeployed.encrypter;
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index 141c8c2a0..9f6ad7a7a 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -1,15 +1,18 @@
import { SecretKey } from '@nucypher/nucypher-core';
-import {
- ConditionContext,
- Conditions,
- ConditionSet,
- Operator,
-} from '../../src';
-import { CustomContextParam } from '../../src/conditions/condition-context';
-import { USER_ADDRESS_PARAM } from '../../src/conditions/conditions';
+import { conditions, CustomContextParam } from '../../src';
+import { RpcConditionConfig } from '../../src/conditions/base/rpc';
+import { USER_ADDRESS_PARAM } from '../../src/conditions/const';
import { fakeWeb3Provider } from '../utils';
+const {
+ predefined: { ERC721Balance },
+ base: { TimelockCondition, RpcCondition, EvmCondition },
+ Operator,
+ ConditionSet,
+ ConditionContext,
+} = conditions;
+
const TEST_CONTRACT_ADDR = '0xC36442b4a4522E871399CD717aBDD847Ab11FE88';
const TEST_CONTRACT_ADDR_2 = '0x5dB11d7356aa4C0E85Aa5b255eC2B5F81De6d4dA';
const TEST_CHAIN_ID = 5;
@@ -25,7 +28,7 @@ describe('operator', () => {
});
describe('conditions schema', () => {
- const condition = new Conditions.ERC721Balance();
+ const condition = new ERC721Balance();
let result = condition.validate({
contractAddress: TEST_CONTRACT_ADDR,
});
@@ -50,10 +53,10 @@ describe('conditions schema', () => {
});
describe('condition set', () => {
- const genuineUndead = new Conditions.ERC721Balance({
+ const genuineUndead = new ERC721Balance({
contractAddress: TEST_CONTRACT_ADDR,
});
- const gnomePals = new Conditions.ERC721Balance({
+ const gnomePals = new ERC721Balance({
contractAddress: TEST_CONTRACT_ADDR_2,
});
const conditions = new ConditionSet([genuineUndead, Operator.AND, gnomePals]);
@@ -84,7 +87,7 @@ describe('standard conditions types validation', () => {
describe('works for valid conditions', () => {
it('timelock', () => {
- const timelock = new Conditions.TimelockCondition({
+ const timelock = new TimelockCondition({
returnValueTest,
});
expect(timelock.toObj()).toEqual({
@@ -100,7 +103,7 @@ describe('standard conditions types validation', () => {
parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
returnValueTest,
};
- const rpc = new Conditions.RpcCondition(rpcCondition);
+ const rpc = new RpcCondition(rpcCondition);
expect(rpc.toObj()).toEqual(rpcCondition);
});
@@ -113,7 +116,7 @@ describe('standard conditions types validation', () => {
parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
returnValueTest,
};
- const evm = new Conditions.EvmCondition(evmCondition);
+ const evm = new EvmCondition(evmCondition);
expect(evm.toObj()).toEqual(evmCondition);
});
});
@@ -128,9 +131,7 @@ describe('standard conditions types validation', () => {
value: '100',
},
};
- const badTimelock = new Conditions.TimelockCondition(
- badTimelockCondition
- );
+ const badTimelock = new TimelockCondition(badTimelockCondition);
expect(() => badTimelock.toObj()).toThrow(
'"returnValueTest.comparator" must be one of [==, >, <, >=, <=, !=]'
);
@@ -148,7 +149,7 @@ describe('standard conditions types validation', () => {
parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
returnValueTest,
};
- const badRpc = new Conditions.RpcCondition(badRpcCondition);
+ const badRpc = new RpcCondition(badRpcCondition);
expect(() => badRpc.toObj()).toThrow(
'"method" must be one of [eth_getBalance, balanceOf]'
);
@@ -168,7 +169,7 @@ describe('standard conditions types validation', () => {
parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
returnValueTest,
};
- const badEvm = new Conditions.EvmCondition(badEvmCondition);
+ const badEvm = new EvmCondition(badEvmCondition);
expect(() => badEvm.toObj()).toThrow('"contractAddress" is required');
const { error } = badEvm.validate(badEvmCondition);
expect(error?.message).toEqual('"contractAddress" is required');
@@ -178,16 +179,18 @@ describe('standard conditions types validation', () => {
describe('produce context parameters from conditions', () => {
describe('from rpc condition', () => {
- const methods = Conditions.RpcCondition.RPC_METHODS;
+ const methods = RpcConditionConfig.RPC_METHODS;
methods.forEach((method) => {
const contextParams =
- Conditions.RpcCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
+ RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[
+ method as keyof typeof RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD
+ ];
if (!contextParams) {
return;
}
contextParams.forEach((contextParam) => {
it(`produces context parameter ${contextParam} for method ${method}`, () => {
- const rpcCondition = new Conditions.RpcCondition({
+ const rpcCondition = new RpcCondition({
chain: 5,
method,
parameters: [contextParam],
@@ -205,21 +208,20 @@ describe('produce context parameters from conditions', () => {
});
describe('from evm condition', () => {
- Conditions.EvmCondition.STANDARD_CONTRACT_TYPES.forEach((contractType) => {
- const methods =
- Conditions.EvmCondition.METHODS_PER_CONTRACT_TYPE[contractType];
+ EvmCondition.STANDARD_CONTRACT_TYPES.forEach((contractType) => {
+ const methods = EvmCondition.METHODS_PER_CONTRACT_TYPE[contractType];
if (!methods) {
return;
}
methods.forEach((method) => {
const contextParams =
- Conditions.EvmCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
+ EvmCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
if (!contextParams) {
return;
}
contextParams.forEach((contextParam) => {
it(`produces context parameter ${contextParam} for method ${method}`, () => {
- const evmCondition = new Conditions.EvmCondition({
+ const evmCondition = new EvmCondition({
contractAddress: '0x0000000000000000000000000000000000000000',
chain: 5,
standardContractType: 'ERC20',
@@ -244,7 +246,7 @@ describe('condition context', () => {
it('should serialize to JSON with context params', async () => {
const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
- const rpcCondition = new Conditions.RpcCondition({
+ const rpcCondition = new RpcCondition({
chain: 5,
method: 'eth_getBalance',
parameters: [USER_ADDRESS_PARAM],
@@ -285,7 +287,7 @@ describe('condition context', () => {
},
],
};
- const evmCondition = new Conditions.EvmCondition({
+ const evmCondition = new EvmCondition({
chain: 5,
functionAbi: fakeFunctionAbi,
method: 'balanceOf',
@@ -351,13 +353,13 @@ describe('evm condition', () => {
it('accepts standardContractType', () => {
const conditionJson = { ...baseEvmCondition, standardContractType };
- const evmCondition = new Conditions.EvmCondition(conditionJson);
+ const evmCondition = new EvmCondition(conditionJson);
expect(evmCondition.toObj()).toEqual(conditionJson);
});
it('accepts functionAbi', () => {
const conditionJson = { ...baseEvmCondition, functionAbi };
- const evmCondition = new Conditions.EvmCondition(conditionJson);
+ const evmCondition = new EvmCondition(conditionJson);
expect(evmCondition.toObj()).toEqual(conditionJson);
});
@@ -367,14 +369,14 @@ describe('evm condition', () => {
standardContractType,
functionAbi,
};
- const evmCondition = new Conditions.EvmCondition(conditionJson);
+ const evmCondition = new EvmCondition(conditionJson);
expect(() => evmCondition.toObj()).toThrow(
'"value" contains a conflict between exclusive peers [standardContractType, functionAbi]'
);
});
it('rejects none', () => {
- const evmCondition = new Conditions.EvmCondition(baseEvmCondition);
+ const evmCondition = new EvmCondition(baseEvmCondition);
expect(() => evmCondition.toObj()).toThrow(
'"value" must contain at least one of [standardContractType, functionAbi]'
);
diff --git a/test/integration/enrico.test.ts b/test/integration/enrico.test.ts
index c45c2e452..58db0616a 100644
--- a/test/integration/enrico.test.ts
+++ b/test/integration/enrico.test.ts
@@ -1,5 +1,6 @@
+// Disabling because we want to access Alice.keyring which is a private property
/* eslint-disable @typescript-eslint/no-explicit-any */
-import { Conditions, ConditionSet, Enrico, PolicyMessageKit } from '../../src';
+import { conditions, Enrico, PolicyMessageKit } from '../../src';
import { RetrievalResult } from '../../src/kits/retrieval';
import { toBytes } from '../../src/utils';
import {
@@ -10,6 +11,11 @@ import {
reencryptKFrags,
} from '../utils';
+const {
+ predefined: { ERC721Ownership },
+ ConditionSet,
+} = conditions;
+
describe('enrico', () => {
it('alice decrypts message encrypted by enrico', async () => {
const label = 'fake-label';
@@ -93,7 +99,7 @@ describe('enrico', () => {
const policyKey = alice.getPolicyEncryptingKeyFromLabel(label);
- const ownsBufficornNFT = Conditions.ERC721Ownership.fromObj({
+ const ownsBufficornNFT = ERC721Ownership.fromObj({
contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
parameters: [3591],
});
@@ -116,13 +122,13 @@ describe('enrico', () => {
const policyKey = alice.getPolicyEncryptingKeyFromLabel(label);
- const ownsBufficornNFT = new Conditions.ERC721Ownership({
+ const ownsBufficornNFT = new ERC721Ownership({
contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
chain: 5,
parameters: [3591],
});
- const ownsNonsenseNFT = new Conditions.ERC721Ownership({
+ const ownsNonsenseNFT = new ERC721Ownership({
contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
chain: 5,
parameters: [6969],
diff --git a/test/integration/pre.test.ts b/test/integration/pre.test.ts
index 106814b19..3c6500d95 100644
--- a/test/integration/pre.test.ts
+++ b/test/integration/pre.test.ts
@@ -1,17 +1,16 @@
import { CapsuleFrag, reencrypt } from '@nucypher/nucypher-core';
-import {
- Conditions,
- ConditionSet,
- Enrico,
- MessageKit,
- Operator,
- PolicyMessageKit,
-} from '../../src';
+import { conditions, Enrico, MessageKit, PolicyMessageKit } from '../../src';
import { RetrievalResult } from '../../src/kits/retrieval';
import { toBytes, zip } from '../../src/utils';
import { fakeAlice, fakeBob, fakeUrsulas, reencryptKFrags } from '../utils';
+const {
+ predefined: { ERC721Ownership },
+ Operator,
+ ConditionSet,
+} = conditions;
+
describe('proxy reencryption', () => {
const plaintext = toBytes('plaintext-message');
const threshold = 2;
@@ -85,21 +84,21 @@ describe('proxy reencryption', () => {
const policyEncryptingKey = alice.getPolicyEncryptingKeyFromLabel(label);
- const genuineUndead = new Conditions.ERC721Ownership({
+ const genuineUndead = new ERC721Ownership({
contractAddress: '0x209e639a0EC166Ac7a1A4bA41968fa967dB30221',
chain: 1,
});
- const gnomePals = new Conditions.ERC721Ownership({
+ const gnomePals = new ERC721Ownership({
contractAddress: '0x5dB11d7356aa4C0E85Aa5b255eC2B5F81De6d4dA',
chain: 1,
});
- const conditions = new ConditionSet([
+ const conditionsSet = new ConditionSet([
genuineUndead,
Operator.OR,
gnomePals,
]);
- const enrico = new Enrico(policyEncryptingKey, undefined, conditions);
+ const enrico = new Enrico(policyEncryptingKey, undefined, conditionsSet);
const encryptedMessage = enrico.encryptMessage(plaintext);
const ursulaAddresses = ursulas.map((ursula) => ursula.checksumAddress);
diff --git a/test/unit/strategy.test.ts b/test/unit/strategy.test.ts
index 5c49eeaa3..5881493c3 100644
--- a/test/unit/strategy.test.ts
+++ b/test/unit/strategy.test.ts
@@ -6,8 +6,7 @@ import {
import {
Cohort,
- Conditions,
- ConditionSet,
+ conditions,
DeployedStrategy,
Strategy,
tDecDecrypter,
@@ -34,6 +33,11 @@ import {
strategyJSON,
} from './testVariables';
+const {
+ predefined: { ERC721Ownership },
+ ConditionSet,
+} = conditions;
+
describe('Strategy', () => {
const cohortConfig = {
threshold: 2,
@@ -195,7 +199,7 @@ describe('Deployed Strategy', () => {
const encrypter = testDeployed.encrypter;
const decrypter = testDeployed.decrypter;
- const ownsNFT = new Conditions.ERC721Ownership({
+ const ownsNFT = new ERC721Ownership({
contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
parameters: [3591],
chain: 5,
diff --git a/tsconfig.json b/tsconfig.json
index 58621b182..07ea4fca0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -23,6 +23,7 @@
"strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
"noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
"alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,
+ "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Additional Checks */
"noUnusedLocals": true /* Report errors on unused locals. */,
From 5c09612f3f9e982a7ccf124ee90c90266617bb3e Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 11 May 2023 13:12:06 +0200
Subject: [PATCH 22/98] refactor conditions into subclasses with interfaces and
a mixin
---
src/characters/porter.ts | 2 +-
src/conditions/base/evm.ts | 89 +++++++++++--------
src/conditions/base/rpc.ts | 74 +++++++++------
src/conditions/base/timelock.ts | 8 +-
src/conditions/condition-set.ts | 14 +--
src/conditions/condition.ts | 84 ++++++++---------
src/conditions/const.ts | 2 +
.../context.ts} | 19 ++--
src/conditions/context/index.ts | 2 +
src/conditions/context/mixin.ts | 38 ++++++++
src/conditions/{ => context}/providers.ts | 11 ++-
src/conditions/index.ts | 4 +-
test/docs/cbd.test.ts | 4 +-
test/integration/conditions.test.ts | 10 ++-
test/integration/enrico.test.ts | 1 +
15 files changed, 219 insertions(+), 143 deletions(-)
rename src/conditions/{condition-context.ts => context/context.ts} (84%)
create mode 100644 src/conditions/context/index.ts
create mode 100644 src/conditions/context/mixin.ts
rename src/conditions/{ => context}/providers.ts (94%)
diff --git a/src/characters/porter.ts b/src/characters/porter.ts
index 243262919..2aa1d7b1c 100644
--- a/src/characters/porter.ts
+++ b/src/characters/porter.ts
@@ -7,7 +7,7 @@ import {
import axios, { AxiosResponse } from 'axios';
import qs from 'qs';
-import { ConditionContext } from '../conditions/condition-context';
+import { ConditionContext } from '../conditions';
import { Base64EncodedBytes, ChecksumAddress, HexEncodedBytes } from '../types';
import { fromBase64, fromHexString, toBase64, toHexString } from '../utils';
diff --git a/src/conditions/base/evm.ts b/src/conditions/base/evm.ts
index ef6aa6bc3..a2e79fd53 100644
--- a/src/conditions/base/evm.ts
+++ b/src/conditions/base/evm.ts
@@ -1,11 +1,41 @@
import Joi from 'joi';
-import { Condition } from '../condition';
-import { SUPPORTED_CHAINS, USER_ADDRESS_PARAM } from '../const';
+import { Condition, makeReturnValueTest } from '../condition';
+import {
+ ETH_ADDRESS_REGEXP,
+ SUPPORTED_CHAINS,
+ USER_ADDRESS_PARAM,
+} from '../const';
+import { ContextParametersHandlerMixin } from '../context/mixin';
+
+export interface EvmConditionConfig {
+ CONDITION_TYPE: string;
+ STANDARD_CONTRACT_TYPES: string[];
+ METHODS_PER_CONTRACT_TYPE: Record;
+ PARAMETERS_PER_METHOD: Record;
+ CONTEXT_PARAMETERS_PER_METHOD: Record;
+}
+
+export const EvmConditionConfig: EvmConditionConfig = {
+ CONDITION_TYPE: 'evm',
+ STANDARD_CONTRACT_TYPES: ['ERC20', 'ERC721'],
+ METHODS_PER_CONTRACT_TYPE: {
+ ERC20: ['balanceOf'],
+ ERC721: ['balanceOf', 'ownerOf'],
+ },
+ PARAMETERS_PER_METHOD: {
+ balanceOf: ['address'],
+ ownerOf: ['tokenId'],
+ },
+ CONTEXT_PARAMETERS_PER_METHOD: {
+ balanceOf: [USER_ADDRESS_PARAM],
+ ownerOf: [USER_ADDRESS_PARAM],
+ },
+};
// A helper method for making complex Joi types
// It says "allow these `types` when `parent` value is given"
-const makeGuard = (
+const makeWhenGuard = (
schema: Joi.StringSchema | Joi.ArraySchema,
types: Record,
parent: string
@@ -19,52 +49,33 @@ const makeGuard = (
return schema;
};
-export class EvmCondition extends Condition {
- public static readonly CONDITION_TYPE = 'evm';
- public static readonly STANDARD_CONTRACT_TYPES = [
- 'ERC20',
- 'ERC721',
- // 'ERC1155', // TODO(#131)
- ];
- public static readonly METHODS_PER_CONTRACT_TYPE: Record = {
- ERC20: ['balanceOf'],
- ERC721: ['balanceOf', 'ownerOf'],
- // ERC1155: ['balanceOf'], // TODO(#131)
- };
- public static readonly PARAMETERS_PER_METHOD: Record = {
- balanceOf: ['address'],
- ownerOf: ['tokenId'],
- };
- public static readonly CONTEXT_PARAMETERS_PER_METHOD: Record<
- string,
- string[]
- > = {
- balanceOf: [USER_ADDRESS_PARAM],
- ownerOf: [USER_ADDRESS_PARAM],
- };
-
- private makeMethod = () =>
- makeGuard(
- Joi.string(),
- EvmCondition.METHODS_PER_CONTRACT_TYPE,
- 'standardContractType'
- );
+const makeMethod = () =>
+ makeWhenGuard(
+ Joi.string(),
+ EvmConditionConfig.METHODS_PER_CONTRACT_TYPE,
+ 'standardContractType'
+ );
+export class EvmConditionBase extends Condition {
public readonly schema = Joi.object({
- contractAddress: Joi.string()
- .pattern(new RegExp('^0x[a-fA-F0-9]{40}$'))
- .required(),
+ contractAddress: Joi.string().pattern(ETH_ADDRESS_REGEXP).required(),
chain: Joi.string()
.valid(...SUPPORTED_CHAINS)
.required(),
standardContractType: Joi.string()
- .valid(...EvmCondition.STANDARD_CONTRACT_TYPES)
+ .valid(...EvmConditionConfig.STANDARD_CONTRACT_TYPES)
.optional(),
functionAbi: Joi.object().optional(),
- method: this.makeMethod().required(),
+ method: makeMethod().required(),
parameters: Joi.array().required(),
- returnValueTest: this.makeReturnValueTest(),
+ returnValueTest: makeReturnValueTest(),
})
// At most one of these keys needs to be present
.xor('standardContractType', 'functionAbi');
}
+
+export const EvmCondition = ContextParametersHandlerMixin(EvmConditionBase);
+
+Object.defineProperty(EvmCondition.prototype, 'getContextConfig', {
+ value: () => EvmConditionConfig.CONTEXT_PARAMETERS_PER_METHOD,
+});
diff --git a/src/conditions/base/rpc.ts b/src/conditions/base/rpc.ts
index 6aeffccf7..9c417f29e 100644
--- a/src/conditions/base/rpc.ts
+++ b/src/conditions/base/rpc.ts
@@ -1,9 +1,21 @@
-import Joi from 'joi';
+import Joi, { Schema } from 'joi';
-import { Condition } from '../condition';
-import { SUPPORTED_CHAINS, USER_ADDRESS_PARAM } from '../const';
+import { Condition, makeReturnValueTest } from '../condition';
+import {
+ ETH_ADDRESS_REGEXP,
+ SUPPORTED_CHAINS,
+ USER_ADDRESS_PARAM,
+} from '../const';
+import { ContextParametersHandlerMixin } from '../context/mixin';
-export const RpcConditionConfig = {
+export interface RpcConditionConfig {
+ CONDITION_TYPE: string;
+ RPC_METHODS: string[];
+ PARAMETERS_PER_METHOD: Record;
+ CONTEXT_PARAMETERS_PER_METHOD: Record;
+}
+
+export const RpcConditionConfig: RpcConditionConfig = {
CONDITION_TYPE: 'rpc',
RPC_METHODS: ['eth_getBalance', 'balanceOf'],
PARAMETERS_PER_METHOD: {
@@ -16,7 +28,27 @@ export const RpcConditionConfig = {
},
};
-export class RpcCondition extends Condition {
+export const ethAddressOrUserAddress = Joi.alternatives().try(
+ Joi.string().pattern(ETH_ADDRESS_REGEXP),
+ USER_ADDRESS_PARAM
+);
+
+export const getAddressSchema = () =>
+ Joi.array().items(ethAddressOrUserAddress).required();
+
+export const rpcMethodSchema = RpcConditionConfig.RPC_METHODS.reduce(
+ (acc, method) => {
+ if (RpcConditionConfig.PARAMETERS_PER_METHOD[method].includes('address')) {
+ acc[method] = getAddressSchema();
+ } else {
+ acc[method] = Joi.array().items(Joi.string()).required();
+ }
+ return acc;
+ },
+ {} as Record
+);
+
+export class RpcConditionBase extends Condition {
public readonly schema = Joi.object({
chain: Joi.number()
.valid(...SUPPORTED_CHAINS)
@@ -24,26 +56,18 @@ export class RpcCondition extends Condition {
method: Joi.string()
.valid(...RpcConditionConfig.RPC_METHODS)
.required(),
- parameters: Joi.array().required(),
- returnValueTest: this.makeReturnValueTest(),
+ parameters: Joi.when('method', {
+ switch: RpcConditionConfig.RPC_METHODS.map((method) => ({
+ is: method,
+ then: rpcMethodSchema[method],
+ })),
+ }),
+ returnValueTest: makeReturnValueTest(),
});
+}
- public getContextParameters = (): string[] => {
- const asObject = this.toObj();
-
- const method = asObject['method'] as string;
- const parameters = (asObject['parameters'] ?? []) as string[];
-
- const context: string[] =
- RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[
- method as keyof typeof RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD
- ];
- const returnValueTest = asObject['returnValueTest'] as Record<
- string,
- string
- >;
+export const RpcCondition = ContextParametersHandlerMixin(RpcConditionBase);
- const maybeParams = [...(context ?? []), returnValueTest['value']];
- return parameters.filter((p) => maybeParams.includes(p));
- };
-}
+Object.defineProperty(RpcCondition.prototype, 'getContextConfig', {
+ value: () => RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD,
+});
diff --git a/src/conditions/base/timelock.ts b/src/conditions/base/timelock.ts
index a42e7431e..d673c0c13 100644
--- a/src/conditions/base/timelock.ts
+++ b/src/conditions/base/timelock.ts
@@ -1,16 +1,14 @@
import Joi from 'joi';
-import { Condition } from '../condition';
+import { Condition, makeReturnValueTest } from '../condition';
export class TimelockCondition extends Condition {
- public static readonly CONDITION_TYPE = 'timelock';
-
defaults = {
method: 'timelock',
};
public readonly schema = Joi.object({
- returnValueTest: this.makeReturnValueTest(),
- method: 'timelock',
+ returnValueTest: makeReturnValueTest(),
+ method: Joi.string().valid('timelock').required(),
});
}
diff --git a/src/conditions/condition-set.ts b/src/conditions/condition-set.ts
index 8165f30a8..afc969889 100644
--- a/src/conditions/condition-set.ts
+++ b/src/conditions/condition-set.ts
@@ -2,13 +2,13 @@ import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
import { Condition } from './condition';
-import { ConditionContext } from './condition-context';
+import { ConditionContext } from './context';
import { Operator } from './operator';
+type ConditionOrOperator = Condition | Operator;
+
export class ConditionSet {
- constructor(
- public readonly conditions: ReadonlyArray
- ) {}
+ constructor(public readonly conditions: ReadonlyArray) {}
public validate() {
if (this.conditions.length % 2 === 0) {
@@ -16,12 +16,12 @@ export class ConditionSet {
'conditions must be odd length, ever other element being an operator'
);
}
- this.conditions.forEach((cnd: Condition | Operator, index) => {
- if (index % 2 && cnd.constructor.name !== 'Operator')
+ this.conditions.forEach((cnd: ConditionOrOperator, index) => {
+ if (index % 2 && !(cnd instanceof Operator))
throw new Error(
`${index} element must be an Operator; Got ${cnd.constructor.name}.`
);
- if (!(index % 2) && cnd.constructor.name === 'Operator')
+ if (!(index % 2) && cnd instanceof Operator)
throw new Error(
`${index} element must be a Condition; Got ${cnd.constructor.name}.`
);
diff --git a/src/conditions/condition.ts b/src/conditions/condition.ts
index 59b0c962c..9fdd26498 100644
--- a/src/conditions/condition.ts
+++ b/src/conditions/condition.ts
@@ -1,8 +1,36 @@
import Joi, { ValidationError } from 'joi';
-export class Condition {
- public static readonly COMPARATORS = ['==', '>', '<', '>=', '<=', '!='];
+export interface ConditionConfig {
+ COMPARATORS: string[];
+}
+
+export interface ReturnValueTestConfig {
+ index?: number;
+ comparator: string;
+ value: string | number;
+}
+
+export const ConditionConfig: ConditionConfig = {
+ COMPARATORS: ['==', '>', '<', '>=', '<=', '!='],
+};
+
+export const makeReturnValueTest =
+ (): Joi.ObjectSchema =>
+ Joi.object({
+ index: Joi.number().optional(),
+ comparator: Joi.string()
+ .valid(...ConditionConfig.COMPARATORS)
+ .required(),
+ value: Joi.alternatives(Joi.string(), Joi.number()).required(),
+ });
+export interface ConditionInterface {
+ schema: Joi.ObjectSchema;
+ defaults: unknown;
+ toObj: () => Record;
+}
+
+export class Condition implements ConditionInterface {
public readonly schema = Joi.object();
public readonly defaults = {};
private validationError?: ValidationError;
@@ -13,16 +41,6 @@ export class Condition {
return this.validationError?.message;
}
- protected makeReturnValueTest() {
- return Joi.object({
- index: Joi.number().optional(),
- comparator: Joi.string()
- .valid(...Condition.COMPARATORS)
- .required(),
- value: Joi.alternatives(Joi.string(), Joi.number()).required(),
- });
- }
-
public toObj(): Record {
const { error, value } = this.validate();
if (error) {
@@ -31,45 +49,17 @@ export class Condition {
return value;
}
- public static fromObj(obj: Record) {
- return new Condition(obj);
+ public static fromObj(
+ // We disable the eslint rule here because we have to pass args to the constructor
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ this: new (...args: any[]) => T,
+ obj: Record
+ ): T {
+ return new this(obj);
}
public validate(data: Record = {}) {
const newValue = Object.assign(this.defaults, this.value, data);
return this.schema.validate(newValue);
}
-
- protected getContextParametersConfig(): Record {
- // Empty configuration object by default, to be implemented by subclasses
- return {};
- }
-
- public getContextParameters(): string[] {
- const asObject = this.toObj();
- let paramsToCheck: string[] = [];
-
- const method = asObject['method'] as string;
- if (method) {
- const contextParams = this.getContextParametersConfig()[method];
- paramsToCheck = [...(contextParams ?? [])];
- }
-
- const returnValueTest = asObject['returnValueTest'] as Record<
- string,
- string
- >;
- if (returnValueTest) {
- paramsToCheck.push(returnValueTest['value']);
- }
-
- paramsToCheck = [
- ...paramsToCheck,
- ...((asObject['parameters'] as string[]) ?? []),
- ];
- const withoutDuplicates = new Set(
- paramsToCheck.filter((p) => paramsToCheck.includes(p))
- );
- return [...withoutDuplicates];
- }
}
diff --git a/src/conditions/const.ts b/src/conditions/const.ts
index f0d3f2ced..19f336649 100644
--- a/src/conditions/const.ts
+++ b/src/conditions/const.ts
@@ -8,3 +8,5 @@ export const SUPPORTED_CHAINS = [
];
export const USER_ADDRESS_PARAM = ':userAddress';
+
+export const ETH_ADDRESS_REGEXP = new RegExp('^0x[a-fA-F0-9]{40}$');
diff --git a/src/conditions/condition-context.ts b/src/conditions/context/context.ts
similarity index 84%
rename from src/conditions/condition-context.ts
rename to src/conditions/context/context.ts
index c63b3dc8a..27d26b76f 100644
--- a/src/conditions/condition-context.ts
+++ b/src/conditions/context/context.ts
@@ -1,9 +1,9 @@
import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
-import { Eip712TypedData } from '../web3';
+import { Eip712TypedData } from '../../web3';
+import { USER_ADDRESS_PARAM } from '../const';
-import { USER_ADDRESS_PARAM } from './const';
import { WalletAuthenticationProvider } from './providers';
interface TypedSignature {
@@ -41,21 +41,22 @@ export class ConditionContext {
await this.walletAuthProvider.getOrCreateWalletSignature();
}
- const conditions = JSON.parse(this.conditions.toString());
- conditions.forEach((cond: { parameters: string[] }) => {
- cond.parameters.forEach((key) => {
+ const parsedConditions = JSON.parse(this.conditions.toString());
+ for (const cond of parsedConditions) {
+ for (const key of cond.parameters) {
if (
!(key in this.customParameters) &&
!SPECIAL_CONTEXT_PARAMS.includes(key)
) {
throw new Error(`Missing custom context parameter ${key}`);
}
- });
- });
+ }
+ }
- Object.keys(this.customParameters).forEach((key) => {
+ for (const key in this.customParameters) {
payload[key] = this.customParameters[key];
- });
+ }
+
return JSON.stringify(payload);
};
diff --git a/src/conditions/context/index.ts b/src/conditions/context/index.ts
new file mode 100644
index 000000000..72a893ff3
--- /dev/null
+++ b/src/conditions/context/index.ts
@@ -0,0 +1,2 @@
+export { ConditionContext } from './context';
+export type { CustomContextParam } from './context';
diff --git a/src/conditions/context/mixin.ts b/src/conditions/context/mixin.ts
new file mode 100644
index 000000000..350bcac0d
--- /dev/null
+++ b/src/conditions/context/mixin.ts
@@ -0,0 +1,38 @@
+import { ConditionInterface } from '../condition';
+
+// Disabling because mixin constructor requires any arguments
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+type Constructor = new (
+ ...params: TParams
+) => TResult;
+
+export function ContextParametersHandlerMixin<
+ TBase extends Constructor
+>(Base: TBase) {
+ return class extends Base {
+ // Disabling because mixin constructor requires any arguments
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ constructor(...args: any[]) {
+ super(...args);
+ }
+
+ public getContextParameters(): string[] {
+ const asObject = this.toObj();
+ const method = asObject['method'] as string;
+ const parameters = (asObject['parameters'] ?? []) as string[];
+ const context = this.getContextConfig()[method];
+
+ const returnValueTest = asObject['returnValueTest'] as Record<
+ string,
+ string
+ >;
+ const maybeParams = [...(context ?? []), returnValueTest['value']];
+ return parameters.filter((p) => maybeParams.includes(p));
+ }
+
+ public getContextConfig(): Record {
+ // Empty configuration object by default
+ return {};
+ }
+ };
+}
diff --git a/src/conditions/providers.ts b/src/conditions/context/providers.ts
similarity index 94%
rename from src/conditions/providers.ts
rename to src/conditions/context/providers.ts
index 907ba87ec..1758fe323 100644
--- a/src/conditions/providers.ts
+++ b/src/conditions/context/providers.ts
@@ -1,13 +1,20 @@
import { ethers } from 'ethers';
import { utils as ethersUtils } from 'ethers/lib/ethers';
-import { Eip712TypedData, FormattedTypedData } from '../web3';
+import { Eip712TypedData, FormattedTypedData } from '../../web3';
interface TypedSignature {
signature: string;
typedData: Eip712TypedData;
address: string;
}
+
+interface ChainData {
+ blockHash: string;
+ chainId: number;
+ blockNumber: number;
+}
+
export class WalletAuthenticationProvider {
private walletSignature?: Record;
@@ -110,7 +117,7 @@ export class WalletAuthenticationProvider {
return { signature, typedData: formattedTypedData, address };
}
- private async getChainData() {
+ private async getChainData(): Promise {
const blockNumber = await this.web3Provider.getBlockNumber();
const blockHash = (await this.web3Provider.getBlock(blockNumber)).hash;
const chainId = (await this.web3Provider.getNetwork()).chainId;
diff --git a/src/conditions/index.ts b/src/conditions/index.ts
index 2e3759a57..0c87df048 100644
--- a/src/conditions/index.ts
+++ b/src/conditions/index.ts
@@ -5,5 +5,5 @@ export { predefined, base };
export { Condition } from './condition';
export { ConditionSet } from './condition-set';
export { Operator } from './operator';
-export type { CustomContextParam } from './condition-context';
-export { ConditionContext } from './condition-context';
+export type { CustomContextParam } from './context';
+export { ConditionContext } from './context';
diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts
index a938959e3..fd5356138 100644
--- a/test/docs/cbd.test.ts
+++ b/test/docs/cbd.test.ts
@@ -67,7 +67,7 @@ describe('Get Started (CBD PoC)', () => {
};
const newCohort = await Cohort.create(config);
- // 3. Specify default predefined
+ // 3. Specify default conditions
const NFTOwnership = new ERC721Ownership({
contractAddress: '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D',
chain: 5, // Tapir network uses Görli testnet
@@ -88,7 +88,7 @@ describe('Get Started (CBD PoC)', () => {
const web3Provider = new providers.Web3Provider(MMprovider, mumbai);
const newDeployed = await newStrategy.deploy('test', web3Provider);
- // 5. Encrypt the plaintext & update predefined
+ // 5. Encrypt the plaintext & update conditions
const NFTBalanceConfig = {
contractAddress: '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D',
standardContractType: 'ERC721',
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
index 9f6ad7a7a..6324dbe27 100644
--- a/test/integration/conditions.test.ts
+++ b/test/integration/conditions.test.ts
@@ -1,6 +1,7 @@
import { SecretKey } from '@nucypher/nucypher-core';
import { conditions, CustomContextParam } from '../../src';
+import { EvmConditionConfig } from '../../src/conditions/base/evm';
import { RpcConditionConfig } from '../../src/conditions/base/rpc';
import { USER_ADDRESS_PARAM } from '../../src/conditions/const';
import { fakeWeb3Provider } from '../utils';
@@ -183,7 +184,7 @@ describe('produce context parameters from conditions', () => {
methods.forEach((method) => {
const contextParams =
RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[
- method as keyof typeof RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD
+ method as keyof RpcConditionConfig
];
if (!contextParams) {
return;
@@ -208,14 +209,15 @@ describe('produce context parameters from conditions', () => {
});
describe('from evm condition', () => {
- EvmCondition.STANDARD_CONTRACT_TYPES.forEach((contractType) => {
- const methods = EvmCondition.METHODS_PER_CONTRACT_TYPE[contractType];
+ EvmConditionConfig.STANDARD_CONTRACT_TYPES.forEach((contractType) => {
+ const methods =
+ EvmConditionConfig.METHODS_PER_CONTRACT_TYPE[contractType];
if (!methods) {
return;
}
methods.forEach((method) => {
const contextParams =
- EvmCondition.CONTEXT_PARAMETERS_PER_METHOD[method];
+ EvmConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[method];
if (!contextParams) {
return;
}
diff --git a/test/integration/enrico.test.ts b/test/integration/enrico.test.ts
index 58db0616a..66318607b 100644
--- a/test/integration/enrico.test.ts
+++ b/test/integration/enrico.test.ts
@@ -102,6 +102,7 @@ describe('enrico', () => {
const ownsBufficornNFT = ERC721Ownership.fromObj({
contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
parameters: [3591],
+ chain: 5,
});
const conditions = new ConditionSet([ownsBufficornNFT]);
From d1b9818b0513f093094d10945fc943c1690b7bcb Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 11 May 2023 14:45:12 +0200
Subject: [PATCH 23/98] feat!: remove unused revoked strategy
---
src/index.ts | 2 +-
src/sdk/strategy.ts | 9 ---------
2 files changed, 1 insertion(+), 10 deletions(-)
diff --git a/src/index.ts b/src/index.ts
index 83dffc869..0e3c7f973 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -21,7 +21,7 @@ export {
} from './conditions/condition-context';
export { Cohort } from './sdk/cohort';
-export { DeployedStrategy, RevokedStrategy, Strategy } from './sdk/strategy';
+export { DeployedStrategy, Strategy } from './sdk/strategy';
export {
PublicKey,
diff --git a/src/sdk/strategy.ts b/src/sdk/strategy.ts
index db713a304..5facc86d2 100644
--- a/src/sdk/strategy.ts
+++ b/src/sdk/strategy.ts
@@ -239,12 +239,3 @@ export class DeployedStrategy {
};
}
}
-
-export class RevokedStrategy {
- constructor(
- public label: string,
- public policy: EnactedPolicy,
- public encrypter: Enrico,
- public decrypter: tDecDecrypter
- ) {}
-}
From 41261843083b01a80587a601a6e068f576e8959c Mon Sep 17 00:00:00 2001
From: piotr-roslaniec <39299780+piotr-roslaniec@users.noreply.github.com>
Date: Thu, 11 May 2023 17:23:01 +0200
Subject: [PATCH 24/98] Fix mainnet porter URL
Co-authored-by: KPrasch
---
src/config.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/config.ts b/src/config.ts
index 7835c14f1..1b59d0c4e 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -17,7 +17,7 @@ const CONFIGS: { readonly [key in ChainId]: Configuration } = {
},
[ChainId.MAINNET]: {
// TODO: Confirm this is correct
- porterUri: 'https://porter.nucypher.community',
+ porterUri: 'https://porter.nucypher.io/',
},
};
From 7887d53c0695b12114c5a10deda8b78daafaeb4e Mon Sep 17 00:00:00 2001
From: piotr-roslaniec <39299780+piotr-roslaniec@users.noreply.github.com>
Date: Thu, 11 May 2023 18:09:49 +0200
Subject: [PATCH 25/98] undefined is not a string
---
src/agents/contracts.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/agents/contracts.ts b/src/agents/contracts.ts
index 1af9f6aba..c6b022421 100644
--- a/src/agents/contracts.ts
+++ b/src/agents/contracts.ts
@@ -22,7 +22,7 @@ const GOERLI: Contracts = {
const MAINNET: Contracts = {
SUBSCRIPTION_MANAGER: undefined,
- COORDINATOR: 'undefined',
+ COORDINATOR: undefined,
};
const CONTRACTS: { readonly [key in ChainId]: Contracts } = {
From 0e180dc7698e1de24bfccebfa7c3897d2092e4e0 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Fri, 12 May 2023 09:02:32 +0200
Subject: [PATCH 26/98] move condition to conditions/base
---
src/conditions/{ => base}/condition.ts | 0
src/conditions/base/evm.ts | 3 ++-
src/conditions/base/index.ts | 1 +
src/conditions/base/rpc.ts | 3 ++-
src/conditions/base/timelock.ts | 2 +-
src/conditions/condition-set.ts | 2 +-
src/conditions/context/mixin.ts | 2 +-
src/conditions/index.ts | 2 +-
8 files changed, 9 insertions(+), 6 deletions(-)
rename src/conditions/{ => base}/condition.ts (100%)
diff --git a/src/conditions/condition.ts b/src/conditions/base/condition.ts
similarity index 100%
rename from src/conditions/condition.ts
rename to src/conditions/base/condition.ts
diff --git a/src/conditions/base/evm.ts b/src/conditions/base/evm.ts
index a2e79fd53..f1b47eb3f 100644
--- a/src/conditions/base/evm.ts
+++ b/src/conditions/base/evm.ts
@@ -1,6 +1,5 @@
import Joi from 'joi';
-import { Condition, makeReturnValueTest } from '../condition';
import {
ETH_ADDRESS_REGEXP,
SUPPORTED_CHAINS,
@@ -8,6 +7,8 @@ import {
} from '../const';
import { ContextParametersHandlerMixin } from '../context/mixin';
+import { Condition, makeReturnValueTest } from './condition';
+
export interface EvmConditionConfig {
CONDITION_TYPE: string;
STANDARD_CONTRACT_TYPES: string[];
diff --git a/src/conditions/base/index.ts b/src/conditions/base/index.ts
index 0942d8b6a..2857b9d63 100644
--- a/src/conditions/base/index.ts
+++ b/src/conditions/base/index.ts
@@ -1,3 +1,4 @@
+export { Condition } from './condition';
export { EvmCondition } from './evm';
export { RpcCondition } from './rpc';
export { TimelockCondition } from './timelock';
diff --git a/src/conditions/base/rpc.ts b/src/conditions/base/rpc.ts
index 9c417f29e..12dff4ab0 100644
--- a/src/conditions/base/rpc.ts
+++ b/src/conditions/base/rpc.ts
@@ -1,6 +1,5 @@
import Joi, { Schema } from 'joi';
-import { Condition, makeReturnValueTest } from '../condition';
import {
ETH_ADDRESS_REGEXP,
SUPPORTED_CHAINS,
@@ -8,6 +7,8 @@ import {
} from '../const';
import { ContextParametersHandlerMixin } from '../context/mixin';
+import { Condition, makeReturnValueTest } from './condition';
+
export interface RpcConditionConfig {
CONDITION_TYPE: string;
RPC_METHODS: string[];
diff --git a/src/conditions/base/timelock.ts b/src/conditions/base/timelock.ts
index d673c0c13..fdf0b3574 100644
--- a/src/conditions/base/timelock.ts
+++ b/src/conditions/base/timelock.ts
@@ -1,6 +1,6 @@
import Joi from 'joi';
-import { Condition, makeReturnValueTest } from '../condition';
+import { Condition, makeReturnValueTest } from './condition';
export class TimelockCondition extends Condition {
defaults = {
diff --git a/src/conditions/condition-set.ts b/src/conditions/condition-set.ts
index afc969889..3ce490b43 100644
--- a/src/conditions/condition-set.ts
+++ b/src/conditions/condition-set.ts
@@ -1,7 +1,7 @@
import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
-import { Condition } from './condition';
+import { Condition } from './base/condition';
import { ConditionContext } from './context';
import { Operator } from './operator';
diff --git a/src/conditions/context/mixin.ts b/src/conditions/context/mixin.ts
index 350bcac0d..6d6d0ed66 100644
--- a/src/conditions/context/mixin.ts
+++ b/src/conditions/context/mixin.ts
@@ -1,4 +1,4 @@
-import { ConditionInterface } from '../condition';
+import { ConditionInterface } from '../base/condition';
// Disabling because mixin constructor requires any arguments
// eslint-disable-next-line @typescript-eslint/no-explicit-any
diff --git a/src/conditions/index.ts b/src/conditions/index.ts
index 0c87df048..32a45fc46 100644
--- a/src/conditions/index.ts
+++ b/src/conditions/index.ts
@@ -2,7 +2,7 @@ import * as base from './base';
import * as predefined from './predefined';
export { predefined, base };
-export { Condition } from './condition';
+export { Condition } from './base/condition';
export { ConditionSet } from './condition-set';
export { Operator } from './operator';
export type { CustomContextParam } from './context';
From 2cee252727b6ae68b00bdeb6e37dd9f5fbaec8d7 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Mon, 15 May 2023 13:17:12 +0200
Subject: [PATCH 27/98] test: refactor test structure
---
src/conditions/condition-set.ts | 17 +-
src/conditions/operator.ts | 4 +-
test/integration/conditions.test.ts | 406 --------------------
test/unit/conditions/base/condition.test.ts | 104 +++++
test/unit/conditions/base/evm.test.ts | 70 ++++
test/unit/conditions/base/rpc.test.ts | 27 ++
test/unit/conditions/base/timelock.test.ts | 39 ++
test/unit/conditions/condition-set.test.ts | 75 ++++
test/unit/conditions/context.test.ts | 152 ++++++++
test/unit/conditions/operator.test.ts | 14 +
test/unit/testVariables.ts | 27 ++
11 files changed, 522 insertions(+), 413 deletions(-)
delete mode 100644 test/integration/conditions.test.ts
create mode 100644 test/unit/conditions/base/condition.test.ts
create mode 100644 test/unit/conditions/base/evm.test.ts
create mode 100644 test/unit/conditions/base/rpc.test.ts
create mode 100644 test/unit/conditions/base/timelock.test.ts
create mode 100644 test/unit/conditions/condition-set.test.ts
create mode 100644 test/unit/conditions/context.test.ts
create mode 100644 test/unit/conditions/operator.test.ts
diff --git a/src/conditions/condition-set.ts b/src/conditions/condition-set.ts
index 3ce490b43..7864c6c6e 100644
--- a/src/conditions/condition-set.ts
+++ b/src/conditions/condition-set.ts
@@ -11,20 +11,25 @@ export class ConditionSet {
constructor(public readonly conditions: ReadonlyArray) {}
public validate() {
+ // Expects [Condition, Operator, Condition, Operator, ...], where the last element is a Condition
+
if (this.conditions.length % 2 === 0) {
throw new Error(
- 'conditions must be odd length, ever other element being an operator'
+ 'conditions must be odd length, every other element being an operator'
);
}
- this.conditions.forEach((cnd: ConditionOrOperator, index) => {
- if (index % 2 && !(cnd instanceof Operator))
+
+ this.conditions.forEach((cndOrOp: ConditionOrOperator, index) => {
+ if (index % 2 && !(cndOrOp instanceof Operator)) {
throw new Error(
- `${index} element must be an Operator; Got ${cnd.constructor.name}.`
+ `index ${index} must be an Operator, got ${cndOrOp.constructor.name} instead`
);
- if (!(index % 2) && cnd instanceof Operator)
+ }
+ if (!(index % 2) && cndOrOp instanceof Operator) {
throw new Error(
- `${index} element must be a Condition; Got ${cnd.constructor.name}.`
+ `index ${index} must be a Condition, got ${cndOrOp.constructor.name} instead`
);
+ }
});
return true;
}
diff --git a/src/conditions/operator.ts b/src/conditions/operator.ts
index e7fdca994..2ef39471c 100644
--- a/src/conditions/operator.ts
+++ b/src/conditions/operator.ts
@@ -5,7 +5,9 @@ export class Operator {
public constructor(public readonly operator: string) {
if (!Operator.LOGICAL_OPERATORS.includes(operator)) {
- throw `"${operator}" is not a valid operator`;
+ throw `"${operator}" must be one of [${Operator.LOGICAL_OPERATORS.join(
+ ', '
+ )}]`;
}
this.operator = operator;
}
diff --git a/test/integration/conditions.test.ts b/test/integration/conditions.test.ts
deleted file mode 100644
index 224b23390..000000000
--- a/test/integration/conditions.test.ts
+++ /dev/null
@@ -1,406 +0,0 @@
-import { SecretKey } from '@nucypher/nucypher-core';
-
-import { conditions, CustomContextParam } from '../../src';
-import { EvmConditionConfig } from '../../src/conditions/base/evm';
-import { RpcConditionConfig } from '../../src/conditions/base/rpc';
-import { USER_ADDRESS_PARAM } from '../../src/conditions/const';
-import { fakeWeb3Provider } from '../utils';
-
-const {
- predefined: { ERC721Balance },
- base: { TimelockCondition, RpcCondition, EvmCondition },
- Operator,
- ConditionSet,
- ConditionContext,
-} = conditions;
-
-const TEST_CONTRACT_ADDR = '0xC36442b4a4522E871399CD717aBDD847Ab11FE88';
-const TEST_CONTRACT_ADDR_2 = '0x5dB11d7356aa4C0E85Aa5b255eC2B5F81De6d4dA';
-const TEST_CHAIN_ID = 5;
-
-describe('operator', () => {
- it('should validate Operator', async () => {
- const op = new Operator('or');
- expect(op.operator).toEqual('or');
- expect(() => {
- new Operator('then');
- }).toThrow();
- });
-});
-
-describe('conditions schema', () => {
- const condition = new ERC721Balance();
- let result = condition.validate({
- contractAddress: TEST_CONTRACT_ADDR,
- });
-
- it('should validate', async () => {
- expect(result.error).toEqual(undefined);
- expect(result.value.contractAddress).toEqual(TEST_CONTRACT_ADDR);
- });
-
- result = condition.validate({ chain: TEST_CHAIN_ID });
- it('should update the value of "chain"', async () => {
- expect(result.error).toEqual(undefined);
- expect(result.value.chain).toEqual(TEST_CHAIN_ID);
- });
-
- it('should validate chain id', async () => {
- result = condition.validate({ chain: 10 });
- expect(result.error?.message).toEqual(
- '"chain" must be one of [1, 5, 137, 80001]'
- );
- });
-});
-
-describe('condition set', () => {
- const genuineUndead = new ERC721Balance({
- contractAddress: TEST_CONTRACT_ADDR,
- });
- const gnomePals = new ERC721Balance({
- contractAddress: TEST_CONTRACT_ADDR_2,
- });
- const conditions = new ConditionSet([genuineUndead, Operator.AND, gnomePals]);
-
- it('should validate', async () => {
- expect(conditions.validate()).toEqual(true);
- });
-});
-
-describe('conditions set to/from json', () => {
- const json = `[{"chain":${TEST_CHAIN_ID},"method":"ownerOf","parameters":["3591"],"standardContractType":"ERC721","returnValueTest":{"comparator":"==","value":":userAddress"},"contractAddress":"${TEST_CONTRACT_ADDR}"}]`;
- const conditionSet = ConditionSet.fromJSON(json);
-
- it('should be a ConditionSet', async () => {
- expect(conditionSet.conditions[0].toObj().contractAddress).toEqual(
- TEST_CONTRACT_ADDR
- );
- expect(conditionSet.toJson()).toEqual(json);
- });
-});
-
-describe('standard conditions types validation', () => {
- const returnValueTest = {
- index: 0,
- comparator: '>',
- value: '100',
- };
-
- describe('works for valid conditions', () => {
- it('timelock', () => {
- const timelock = new TimelockCondition({
- returnValueTest,
- });
- expect(timelock.toObj()).toEqual({
- returnValueTest,
- method: 'timelock',
- });
- });
-
- it('rpc', () => {
- const rpcCondition = {
- chain: 5,
- method: 'eth_getBalance',
- parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
- returnValueTest,
- };
- const rpc = new RpcCondition(rpcCondition);
- expect(rpc.toObj()).toEqual(rpcCondition);
- });
-
- it('evm', () => {
- const evmCondition = {
- contractAddress: '0x0000000000000000000000000000000000000000',
- chain: 5,
- standardContractType: 'ERC20',
- method: 'balanceOf',
- parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
- returnValueTest,
- };
- const evm = new EvmCondition(evmCondition);
- expect(evm.toObj()).toEqual(evmCondition);
- });
- });
-
- describe('fails for invalid conditions', () => {
- it('invalid timelock', () => {
- const badTimelockCondition = {
- // Intentionally replacing `returnValueTest` with an invalid test
- returnValueTest: {
- index: 0,
- comparator: 'not-a-comparator',
- value: '100',
- },
- };
- const badTimelock = new TimelockCondition(badTimelockCondition);
- expect(() => badTimelock.toObj()).toThrow(
- '"returnValueTest.comparator" must be one of [==, >, <, >=, <=, !=]'
- );
- const { error } = badTimelock.validate(badTimelockCondition);
- expect(error?.message).toEqual(
- '"returnValueTest.comparator" must be one of [==, >, <, >=, <=, !=]'
- );
- });
-
- it('invalid rpc', () => {
- const badRpcCondition = {
- chain: 5,
- // Intentionally replacing `method` with an invalid method
- method: 'fake_invalid_method',
- parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
- returnValueTest,
- };
- const badRpc = new RpcCondition(badRpcCondition);
- expect(() => badRpc.toObj()).toThrow(
- '"method" must be one of [eth_getBalance, balanceOf]'
- );
- const { error } = badRpc.validate(badRpcCondition);
- expect(error?.message).toEqual(
- '"method" must be one of [eth_getBalance, balanceOf]'
- );
- });
-
- it('invalid evm', () => {
- const badEvmCondition = {
- // Intentionally removing `contractAddress`
- // contractAddress: '0x0000000000000000000000000000000000000000',
- chain: 5,
- standardContractType: 'ERC20',
- method: 'balanceOf',
- parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
- returnValueTest,
- };
- const badEvm = new EvmCondition(badEvmCondition);
- expect(() => badEvm.toObj()).toThrow('"contractAddress" is required');
- const { error } = badEvm.validate(badEvmCondition);
- expect(error?.message).toEqual('"contractAddress" is required');
- });
- });
-});
-
-describe('produce context parameters from conditions', () => {
- describe('from rpc condition', () => {
- const methods = RpcConditionConfig.RPC_METHODS;
- methods.forEach((method) => {
- const contextParams =
- RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[
- method as keyof RpcConditionConfig
- ];
- if (!contextParams) {
- return;
- }
- contextParams.forEach((contextParam) => {
- it(`produces context parameter ${contextParam} for method ${method}`, () => {
- const rpcCondition = new RpcCondition({
- chain: 5,
- method,
- parameters: [contextParam],
- returnValueTest: {
- index: 0,
- comparator: '==',
- value: contextParam,
- },
- });
- const producedContextParam = rpcCondition.getContextParameters();
- expect(producedContextParam).toEqual([contextParam]);
- });
- });
- });
- });
-
- describe('from evm condition', () => {
- EvmConditionConfig.STANDARD_CONTRACT_TYPES.forEach((contractType) => {
- const methods =
- EvmConditionConfig.METHODS_PER_CONTRACT_TYPE[contractType];
- if (!methods) {
- return;
- }
- methods.forEach((method) => {
- const contextParams =
- EvmConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[method];
- if (!contextParams) {
- return;
- }
- contextParams.forEach((contextParam) => {
- it(`produces context parameter ${contextParam} for method ${method}`, () => {
- const evmCondition = new EvmCondition({
- contractAddress: '0x0000000000000000000000000000000000000000',
- chain: 5,
- standardContractType: 'ERC20',
- method: 'balanceOf',
- parameters: [contextParam],
- returnValueTest: {
- index: 0,
- comparator: '==',
- value: contextParam,
- },
- });
- const producedContextParam = evmCondition.getContextParameters();
- expect(producedContextParam).toEqual([contextParam]);
- });
- });
- });
- });
- });
-});
-
-describe('condition context', () => {
- it('should serialize to JSON with context params', async () => {
- const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
-
- const rpcCondition = new RpcCondition({
- chain: 5,
- method: 'eth_getBalance',
- parameters: [USER_ADDRESS_PARAM],
- returnValueTest: {
- index: 0,
- comparator: '==',
- value: USER_ADDRESS_PARAM,
- },
- });
- const conditionSet = new ConditionSet([rpcCondition]);
-
- const conditionContext = new ConditionContext(
- conditionSet.toWASMConditions(),
- web3Provider
- );
- const asJson = await conditionContext.toJson();
- expect(asJson).toContain(USER_ADDRESS_PARAM);
- });
-
- describe('supports user-defined parameters', () => {
- const fakeFunctionAbi = {
- name: 'myFunction',
- type: 'function',
- inputs: [
- {
- name: 'account',
- type: 'address',
- },
- {
- name: 'myCustomParam',
- type: 'uint256',
- },
- ],
- outputs: [
- {
- name: 'someValue',
- type: 'uint256',
- },
- ],
- };
- const evmConditionObj = {
- chain: 5,
- functionAbi: fakeFunctionAbi,
- method: 'balanceOf',
- contractAddress: '0x0000000000000000000000000000000000000000',
- parameters: [USER_ADDRESS_PARAM, ':customParam'],
- returnValueTest: {
- index: 0,
- comparator: '==',
- value: USER_ADDRESS_PARAM,
- },
- };
- const evmCondition = new EvmCondition(evmConditionObj);
- const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
- const conditionSet = new ConditionSet([evmCondition]);
- const conditionContext = new ConditionContext(
- conditionSet.toWASMConditions(),
- web3Provider
- );
- const myCustomParam = ':customParam';
- const customParams: Record = {};
- customParams[myCustomParam] = 1234;
-
- it('parses user-provided context parameters', async () => {
- const asJson = await conditionContext
- .withCustomParams(customParams)
- .toJson();
- expect(asJson).toBeDefined();
- expect(asJson).toContain(USER_ADDRESS_PARAM);
- expect(asJson).toContain(myCustomParam);
- });
-
- it('throws on missing custom context param', async () => {
- await expect(conditionContext.toJson()).rejects.toThrow(
- `Missing custom context parameter ${myCustomParam}`
- );
- });
-
- it('throws on using reserved context parameter identifiers', () => {
- const badCustomParams: Record = {};
- badCustomParams[USER_ADDRESS_PARAM] = 'this-will-throw';
-
- expect(() => conditionContext.withCustomParams(badCustomParams)).toThrow(
- `Cannot use reserved parameter name ${USER_ADDRESS_PARAM} as custom parameter`
- );
- });
-
- it('accepts custom parameters in predefined methods', async () => {
- const customEvmCondition = new EvmCondition({
- ...evmConditionObj,
- parameters: [myCustomParam],
- });
- const conditionSet = new ConditionSet([customEvmCondition]);
- const conditionContext = new ConditionContext(
- conditionSet.toWASMConditions(),
- web3Provider
- );
-
- const asJson = await conditionContext
- .withCustomParams(customParams)
- .toJson();
- expect(asJson).toBeDefined();
- expect(asJson).toContain(myCustomParam);
- });
- });
-});
-
-describe('evm condition', () => {
- describe('accepts either standardContractType or functionAbi but not both or none', () => {
- const baseEvmCondition = {
- contractAddress: '0x0000000000000000000000000000000000000000',
- chain: 5,
- method: 'balanceOf',
- parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
- returnValueTest: {
- index: 0,
- comparator: '==',
- value: USER_ADDRESS_PARAM,
- },
- };
- const standardContractType = 'ERC20';
- const functionAbi = { fake_function_abi: true };
-
- it('accepts standardContractType', () => {
- const conditionJson = { ...baseEvmCondition, standardContractType };
- const evmCondition = new EvmCondition(conditionJson);
- expect(evmCondition.toObj()).toEqual(conditionJson);
- });
-
- it('accepts functionAbi', () => {
- const conditionJson = { ...baseEvmCondition, functionAbi };
- const evmCondition = new EvmCondition(conditionJson);
- expect(evmCondition.toObj()).toEqual(conditionJson);
- });
-
- it('rejects both', () => {
- const conditionJson = {
- ...baseEvmCondition,
- standardContractType,
- functionAbi,
- };
- const evmCondition = new EvmCondition(conditionJson);
- expect(() => evmCondition.toObj()).toThrow(
- '"value" contains a conflict between exclusive peers [standardContractType, functionAbi]'
- );
- });
-
- it('rejects none', () => {
- const evmCondition = new EvmCondition(baseEvmCondition);
- expect(() => evmCondition.toObj()).toThrow(
- '"value" must contain at least one of [standardContractType, functionAbi]'
- );
- });
- });
-});
diff --git a/test/unit/conditions/base/condition.test.ts b/test/unit/conditions/base/condition.test.ts
new file mode 100644
index 000000000..77a1dfba3
--- /dev/null
+++ b/test/unit/conditions/base/condition.test.ts
@@ -0,0 +1,104 @@
+import {
+ EvmCondition,
+ EvmConditionConfig,
+} from '../../../../src/conditions/base/evm';
+import {
+ RpcCondition,
+ RpcConditionConfig,
+} from '../../../../src/conditions/base/rpc';
+import { ERC721Balance } from '../../../../src/conditions/predefined';
+import {
+ TEST_CHAIN_ID,
+ TEST_CONTRACT_ADDR,
+ testEvmConditionObj,
+ testReturnValueTest,
+ testRpcConditionObj,
+} from '../../testVariables';
+
+describe('validation', () => {
+ const condition = new ERC721Balance();
+ let result = condition.validate({
+ contractAddress: TEST_CONTRACT_ADDR,
+ chain: TEST_CHAIN_ID,
+ });
+
+ it('accepts a correct schema', async () => {
+ expect(result.error).toBeUndefined();
+ expect(result.value.contractAddress).toEqual(TEST_CONTRACT_ADDR);
+ });
+
+ it('updates on a valid schema value', async () => {
+ result = condition.validate({ chain: TEST_CHAIN_ID });
+ expect(result.error).toBeUndefined();
+ expect(result.value.chain).toEqual(TEST_CHAIN_ID);
+ });
+
+ it('rejects on an invalid schema value', async () => {
+ result = condition.validate({ chain: -1 });
+ expect(result.error?.message).toEqual(
+ '"chain" must be one of [1, 5, 137, 80001]'
+ );
+ });
+});
+
+describe('get context parameters from conditions', () => {
+ describe('from rpc condition', () => {
+ const methods = RpcConditionConfig.RPC_METHODS;
+ methods.forEach((method) => {
+ const contextParams =
+ RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[
+ method as keyof RpcConditionConfig
+ ];
+ if (!contextParams) {
+ return;
+ }
+ contextParams.forEach((contextParam) => {
+ it(`gets ${contextParam} for method ${method}`, () => {
+ const rpcCondition = new RpcCondition({
+ ...testRpcConditionObj,
+ method,
+ parameters: [contextParam],
+ returnValueTest: {
+ ...testReturnValueTest,
+ value: contextParam,
+ },
+ });
+
+ const producedContextParam = rpcCondition.getContextParameters();
+ expect(producedContextParam).toEqual([contextParam]);
+ });
+ });
+ });
+ });
+
+ describe('from evm condition', () => {
+ EvmConditionConfig.STANDARD_CONTRACT_TYPES.forEach((contractType) => {
+ const methods =
+ EvmConditionConfig.METHODS_PER_CONTRACT_TYPE[contractType];
+ if (!methods) {
+ return;
+ }
+ methods.forEach((method) => {
+ const contextParams =
+ EvmConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[method];
+ if (!contextParams) {
+ return;
+ }
+ contextParams.forEach((contextParam) => {
+ it(`gets ${contextParam} for method ${method}`, () => {
+ const evmCondition = new EvmCondition({
+ ...testEvmConditionObj,
+ parameters: [contextParam],
+ returnValueTest: {
+ ...testReturnValueTest,
+ value: contextParam,
+ },
+ });
+ const producedContextParam = evmCondition.getContextParameters();
+ expect(producedContextParam).toEqual([contextParam]);
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/test/unit/conditions/base/evm.test.ts b/test/unit/conditions/base/evm.test.ts
new file mode 100644
index 000000000..a417c9b6f
--- /dev/null
+++ b/test/unit/conditions/base/evm.test.ts
@@ -0,0 +1,70 @@
+import { EvmCondition } from '../../../../src/conditions/base';
+import { testEvmConditionObj } from '../../testVariables';
+
+describe('validation', () => {
+ it('accepts on a valid schema', () => {
+ const evm = new EvmCondition(testEvmConditionObj);
+ expect(evm.toObj()).toEqual(testEvmConditionObj);
+ });
+
+ it('rejects an invalid schema', () => {
+ const badEvmCondition = {
+ ...testEvmConditionObj,
+ // Intentionally removing `contractAddress`
+ contractAddress: undefined,
+ };
+ const badEvm = new EvmCondition(badEvmCondition);
+ expect(() => badEvm.toObj()).toThrow('"contractAddress" is required');
+ const { error } = badEvm.validate(badEvmCondition);
+ expect(error?.message).toEqual('"contractAddress" is required');
+ });
+});
+
+describe('accepts either standardContractType or functionAbi but not both or none', () => {
+ const standardContractType = 'ERC20';
+ const functionAbi = { fake_function_abi: true };
+
+ it('accepts standardContractType', () => {
+ const conditionObj = {
+ ...testEvmConditionObj,
+ standardContractType,
+ functionAbi: undefined,
+ };
+ const evmCondition = new EvmCondition(conditionObj);
+ expect(evmCondition.toObj()).toEqual(conditionObj);
+ });
+
+ it('accepts functionAbi', () => {
+ const conditionObj = {
+ ...testEvmConditionObj,
+ functionAbi,
+ standardContractType: undefined,
+ };
+ const evmCondition = new EvmCondition(conditionObj);
+ expect(evmCondition.toObj()).toEqual(conditionObj);
+ });
+
+ it('rejects both', () => {
+ const conditionObj = {
+ ...testEvmConditionObj,
+ standardContractType,
+ functionAbi,
+ };
+ const evmCondition = new EvmCondition(conditionObj);
+ expect(() => evmCondition.toObj()).toThrow(
+ '"value" contains a conflict between exclusive peers [standardContractType, functionAbi]'
+ );
+ });
+
+ it('rejects none', () => {
+ const conditionObj = {
+ ...testEvmConditionObj,
+ standardContractType: undefined,
+ functionAbi: undefined,
+ };
+ const evmCondition = new EvmCondition(conditionObj);
+ expect(() => evmCondition.toObj()).toThrow(
+ '"value" must contain at least one of [standardContractType, functionAbi]'
+ );
+ });
+});
diff --git a/test/unit/conditions/base/rpc.test.ts b/test/unit/conditions/base/rpc.test.ts
new file mode 100644
index 000000000..3b8f3a652
--- /dev/null
+++ b/test/unit/conditions/base/rpc.test.ts
@@ -0,0 +1,27 @@
+import { RpcCondition } from '../../../../src/conditions/base';
+import { testRpcConditionObj } from '../../testVariables';
+
+describe('validation', () => {
+ it('accepts on a valid schema', () => {
+ const rpc = new RpcCondition(testRpcConditionObj);
+ expect(rpc.toObj()).toEqual(testRpcConditionObj);
+ });
+
+ it('rejects an invalid schema', () => {
+ const badRpcObj = {
+ ...testRpcConditionObj,
+ // Intentionally replacing `method` with an invalid method
+ method: 'fake_invalid_method',
+ };
+
+ const badRpc = new RpcCondition(badRpcObj);
+ expect(() => badRpc.toObj()).toThrow(
+ '"method" must be one of [eth_getBalance, balanceOf]'
+ );
+
+ const { error } = badRpc.validate(badRpcObj);
+ expect(error?.message).toEqual(
+ '"method" must be one of [eth_getBalance, balanceOf]'
+ );
+ });
+});
diff --git a/test/unit/conditions/base/timelock.test.ts b/test/unit/conditions/base/timelock.test.ts
new file mode 100644
index 000000000..5d04dc212
--- /dev/null
+++ b/test/unit/conditions/base/timelock.test.ts
@@ -0,0 +1,39 @@
+import { TimelockCondition } from '../../../../src/conditions/base';
+
+describe('validation', () => {
+ const returnValueTest = {
+ index: 0,
+ comparator: '>',
+ value: '100',
+ };
+
+ it('accepts a valid schema', () => {
+ const timelock = new TimelockCondition({
+ returnValueTest,
+ });
+ expect(timelock.toObj()).toEqual({
+ returnValueTest,
+ method: 'timelock',
+ });
+ });
+
+ it('rejects an invalid schema', () => {
+ const badTimelockObj = {
+ // Intentionally replacing `returnValueTest` with an invalid test
+ returnValueTest: {
+ ...returnValueTest,
+ comparator: 'not-a-comparator',
+ },
+ };
+
+ const badTimelock = new TimelockCondition(badTimelockObj);
+ expect(() => badTimelock.toObj()).toThrow(
+ '"returnValueTest.comparator" must be one of [==, >, <, >=, <=, !=]'
+ );
+
+ const { error } = badTimelock.validate(badTimelockObj);
+ expect(error?.message).toEqual(
+ '"returnValueTest.comparator" must be one of [==, >, <, >=, <=, !=]'
+ );
+ });
+});
diff --git a/test/unit/conditions/condition-set.test.ts b/test/unit/conditions/condition-set.test.ts
new file mode 100644
index 000000000..8a9ec9be7
--- /dev/null
+++ b/test/unit/conditions/condition-set.test.ts
@@ -0,0 +1,75 @@
+import { Condition, ConditionSet, Operator } from '../../../src/conditions';
+import { ERC721Balance } from '../../../src/conditions/predefined';
+import {
+ TEST_CHAIN_ID,
+ TEST_CONTRACT_ADDR,
+ TEST_CONTRACT_ADDR_2,
+} from '../testVariables';
+
+describe('condition set', () => {
+ describe('validation', () => {
+ const cond1 = new ERC721Balance({
+ contractAddress: TEST_CONTRACT_ADDR,
+ });
+ const cond2 = new ERC721Balance({
+ contractAddress: TEST_CONTRACT_ADDR_2,
+ });
+
+ it('validates on a correct set', async () => {
+ const validSets = [[cond1, Operator.AND, cond2], [cond1]].map(
+ (set) => new ConditionSet(set)
+ );
+
+ validSets.forEach((set) => {
+ expect(set.validate()).toBeTruthy();
+ });
+ });
+
+ it('throws on an invalid set', async () => {
+ const setWithInvalidLength = new ConditionSet([cond1, cond2]);
+ expect(() => setWithInvalidLength.validate()).toThrow(
+ 'conditions must be odd length, every other element being an operator'
+ );
+
+ const setWithOperatorInsteadOfComparator = new ConditionSet([
+ cond1,
+ Operator.AND,
+ Operator.AND,
+ ]);
+ expect(() => setWithOperatorInsteadOfComparator.validate()).toThrow(
+ 'index 2 must be a Condition, got Operator instead'
+ );
+
+ const setWithConditionInsteadOfOperator = new ConditionSet([
+ cond1,
+ cond2,
+ cond1,
+ ]);
+ expect(() => setWithConditionInsteadOfOperator.validate()).toThrow(
+ 'index 1 must be an Operator, got ERC721Balance instead'
+ );
+ });
+ });
+
+ describe('serialization', () => {
+ it('serializes to and from json', async () => {
+ const set = new ConditionSet([
+ new ERC721Balance({
+ chain: TEST_CHAIN_ID,
+ contractAddress: TEST_CONTRACT_ADDR,
+ }),
+ ]);
+ const setJson = set.toJson();
+ expect(setJson).toBeDefined();
+ expect(setJson).toContain('chain');
+ expect(setJson).toContain(TEST_CHAIN_ID.toString());
+ expect(setJson).toContain('contractAddress');
+ expect(setJson).toContain(TEST_CONTRACT_ADDR.toString());
+
+ const setFromJson = ConditionSet.fromJSON(setJson);
+ expect(setFromJson).toBeDefined();
+ expect(setFromJson.conditions.length).toEqual(1);
+ expect(setFromJson.conditions[0]).toBeInstanceOf(Condition); // TODO: This should arguably be an ERC721Balance
+ });
+ });
+});
diff --git a/test/unit/conditions/context.test.ts b/test/unit/conditions/context.test.ts
new file mode 100644
index 000000000..d26775f2e
--- /dev/null
+++ b/test/unit/conditions/context.test.ts
@@ -0,0 +1,152 @@
+import { SecretKey } from '@nucypher/nucypher-core';
+
+import { CustomContextParam } from '../../../src';
+import { ConditionContext, ConditionSet } from '../../../src/conditions';
+import { EvmCondition, RpcCondition } from '../../../src/conditions/base';
+import { USER_ADDRESS_PARAM } from '../../../src/conditions/const';
+import { fakeWeb3Provider } from '../../utils';
+import { testEvmConditionObj, testRpcConditionObj } from '../testVariables';
+
+describe('condition context', () => {
+ it('should serialize to JSON with context params', async () => {
+ const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
+
+ const rpcCondition = new RpcCondition({
+ ...testRpcConditionObj,
+ parameters: [USER_ADDRESS_PARAM],
+ returnValueTest: {
+ index: 0,
+ comparator: '==',
+ value: USER_ADDRESS_PARAM,
+ },
+ });
+ const conditionSet = new ConditionSet([rpcCondition]);
+
+ const conditionContext = new ConditionContext(
+ conditionSet.toWASMConditions(),
+ web3Provider
+ );
+ const asJson = await conditionContext.toJson();
+ expect(asJson).toContain(USER_ADDRESS_PARAM);
+ });
+
+ describe('supports user-defined parameters', () => {
+ const evmConditionObj = {
+ ...testEvmConditionObj,
+ standardContractType: 'ERC20',
+ method: 'balanceOf',
+ parameters: [USER_ADDRESS_PARAM, ':customParam'],
+ returnValueTest: {
+ index: 0,
+ comparator: '==',
+ value: USER_ADDRESS_PARAM,
+ },
+ };
+ const evmCondition = new EvmCondition(evmConditionObj);
+ const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
+ const conditionSet = new ConditionSet([evmCondition]);
+ const conditionContext = new ConditionContext(
+ conditionSet.toWASMConditions(),
+ web3Provider
+ );
+ const myCustomParam = ':customParam';
+ const customParams: Record = {};
+ customParams[myCustomParam] = 1234;
+
+ it('accepts user-provided context parameters', async () => {
+ const asJson = await conditionContext
+ .withCustomParams(customParams)
+ .toJson();
+ expect(asJson).toBeDefined();
+ expect(asJson).toContain(USER_ADDRESS_PARAM);
+ expect(asJson).toContain(myCustomParam);
+ });
+
+ it('throws on missing custom context param', async () => {
+ await expect(conditionContext.toJson()).rejects.toThrow(
+ `Missing custom context parameter ${myCustomParam}`
+ );
+ });
+
+ it('throws on using reserved context parameter identifiers', () => {
+ const badCustomParams: Record = {};
+ badCustomParams[USER_ADDRESS_PARAM] = 'this-will-throw';
+
+ expect(() => conditionContext.withCustomParams(badCustomParams)).toThrow(
+ `Cannot use reserved parameter name ${USER_ADDRESS_PARAM} as custom parameter`
+ );
+ });
+
+ it('accepts custom parameters in predefined methods', async () => {
+ const customEvmCondition = new EvmCondition({
+ ...evmConditionObj,
+ parameters: [myCustomParam],
+ });
+ const conditionSet = new ConditionSet([customEvmCondition]);
+ const conditionContext = new ConditionContext(
+ conditionSet.toWASMConditions(),
+ web3Provider
+ );
+
+ const asJson = await conditionContext
+ .withCustomParams(customParams)
+ .toJson();
+ expect(asJson).toBeDefined();
+ expect(asJson).toContain(myCustomParam);
+ });
+ });
+
+ // TODO: Fix this test. Fails with '"method" must be [balanceOf]'
+ // describe('supports custom function abi', () => {
+ // const fakeFunctionAbi = {
+ // name: 'myFunction',
+ // type: 'function',
+ // inputs: [
+ // {
+ // name: 'account',
+ // type: 'address',
+ // },
+ // {
+ // name: 'myCustomParam',
+ // type: 'uint256',
+ // },
+ // ],
+ // outputs: [
+ // {
+ // name: 'someValue',
+ // type: 'uint256',
+ // },
+ // ],
+ // };
+ // const evmConditionObj = {
+ // ...testEvmConditionObj,
+ // functionAbi: fakeFunctionAbi,
+ // method: 'myFunction',
+ // parameters: [USER_ADDRESS_PARAM, ':customParam'],
+ // returnValueTest: {
+ // index: 0,
+ // comparator: '==',
+ // value: USER_ADDRESS_PARAM,
+ // },
+ // };
+ // const evmCondition = new EvmCondition(evmConditionObj);
+ // const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
+ // const conditionSet = new ConditionSet([evmCondition]);
+ // const conditionContext = new ConditionContext(
+ // conditionSet.toWASMConditions(),
+ // web3Provider
+ // );
+ // const myCustomParam = ':customParam';
+ // const customParams: Record = {};
+ // customParams[myCustomParam] = 1234;
+ //
+ // it('accepts custom function abi', async () => {
+ // const asJson = await conditionContext
+ // .withCustomParams(customParams)
+ // .toJson();
+ // expect(asJson).toBeDefined();
+ // expect(asJson).toContain(USER_ADDRESS_PARAM);
+ // expect(asJson).toContain(myCustomParam);
+ // });
+ // });
+});
diff --git a/test/unit/conditions/operator.test.ts b/test/unit/conditions/operator.test.ts
new file mode 100644
index 000000000..c6c4d3ed6
--- /dev/null
+++ b/test/unit/conditions/operator.test.ts
@@ -0,0 +1,14 @@
+import { Operator } from '../../../src/conditions';
+
+describe('validate', () => {
+ it('accepts a valid operator', () => {
+ const op = new Operator('or');
+ expect(op.operator).toEqual('or');
+ });
+
+ it('rejects an invalid operator', () => {
+ expect(() => new Operator('not-an-operator')).toThrow(
+ '"not-an-operator" must be one of [and, or]'
+ );
+ });
+});
diff --git a/test/unit/testVariables.ts b/test/unit/testVariables.ts
index 34c1cc099..f577291ef 100644
--- a/test/unit/testVariables.ts
+++ b/test/unit/testVariables.ts
@@ -63,3 +63,30 @@ export const decrypterJSON = JSON.stringify({
'base64:A3yU8aavNj4LJ97eFAaYpU97q70oSogzBZAlo5tj/1Kj',
bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
});
+
+export const TEST_CONTRACT_ADDR = '0x0000000000000000000000000000000000000001';
+export const TEST_CONTRACT_ADDR_2 =
+ '0x0000000000000000000000000000000000000001';
+export const TEST_CHAIN_ID = 5;
+
+export const testReturnValueTest = {
+ index: 0,
+ comparator: '>',
+ value: '100',
+};
+
+export const testRpcConditionObj = {
+ chain: TEST_CHAIN_ID,
+ method: 'eth_getBalance',
+ parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
+ returnValueTest: testReturnValueTest,
+};
+
+export const testEvmConditionObj = {
+ contractAddress: '0x0000000000000000000000000000000000000000',
+ chain: 5,
+ standardContractType: 'ERC20',
+ method: 'balanceOf',
+ parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
+ returnValueTest: testReturnValueTest,
+};
From d1e362e27c56e9206cc0f3445674f9666db8e567 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Mon, 15 May 2023 13:31:50 +0200
Subject: [PATCH 28/98] chore: add codecov to ci
---
.github/workflows/main.yml | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 3e1a202b0..1ddfad165 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -31,6 +31,11 @@ jobs:
- name: Check
run: yarn run package-check
+ - name: Upload coverage to Codecov
+ uses: codecov/codecov-action@v3
+ with:
+ fail_ci_if_error: true
+
build_examples:
name: Build project examples
From 68c69dac7e401cdafd3a96531168afc26f59c849 Mon Sep 17 00:00:00 2001
From: piotr-roslaniec <39299780+piotr-roslaniec@users.noreply.github.com>
Date: Mon, 15 May 2023 15:46:16 +0200
Subject: [PATCH 29/98] test: fix bad contract address
---
test/unit/testVariables.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/test/unit/testVariables.ts b/test/unit/testVariables.ts
index f577291ef..f40efbc5c 100644
--- a/test/unit/testVariables.ts
+++ b/test/unit/testVariables.ts
@@ -66,7 +66,7 @@ export const decrypterJSON = JSON.stringify({
export const TEST_CONTRACT_ADDR = '0x0000000000000000000000000000000000000001';
export const TEST_CONTRACT_ADDR_2 =
- '0x0000000000000000000000000000000000000001';
+ '0x0000000000000000000000000000000000000002';
export const TEST_CHAIN_ID = 5;
export const testReturnValueTest = {
From 2dfebd64dedbaaf5f1e6df0c3574a81f52eee8ca Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Mon, 15 May 2023 20:04:38 +0200
Subject: [PATCH 30/98] fix context parameters
---
src/conditions/base/condition.ts | 22 +--
src/conditions/base/evm.ts | 36 ++--
src/conditions/base/rpc.ts | 18 +-
src/conditions/base/timelock.ts | 6 +-
src/conditions/context/context.ts | 82 ++++++---
src/conditions/context/mixin.ts | 38 ----
src/conditions/context/providers.ts | 2 +-
test/docs/cbd.test.ts | 4 +-
test/unit/conditions/base/condition.test.ts | 86 +--------
test/unit/conditions/base/evm.test.ts | 92 ++++++++++
test/unit/conditions/context.test.ts | 188 ++++++++------------
test/unit/testVariables.ts | 21 +++
12 files changed, 286 insertions(+), 309 deletions(-)
delete mode 100644 src/conditions/context/mixin.ts
diff --git a/src/conditions/base/condition.ts b/src/conditions/base/condition.ts
index 9fdd26498..f8711fba3 100644
--- a/src/conditions/base/condition.ts
+++ b/src/conditions/base/condition.ts
@@ -1,8 +1,6 @@
import Joi, { ValidationError } from 'joi';
-export interface ConditionConfig {
- COMPARATORS: string[];
-}
+const COMPARATORS = ['==', '>', '<', '>=', '<=', '!='];
export interface ReturnValueTestConfig {
index?: number;
@@ -10,29 +8,21 @@ export interface ReturnValueTestConfig {
value: string | number;
}
-export const ConditionConfig: ConditionConfig = {
- COMPARATORS: ['==', '>', '<', '>=', '<=', '!='],
-};
-
export const makeReturnValueTest =
(): Joi.ObjectSchema =>
Joi.object({
index: Joi.number().optional(),
comparator: Joi.string()
- .valid(...ConditionConfig.COMPARATORS)
+ .valid(...COMPARATORS)
.required(),
value: Joi.alternatives(Joi.string(), Joi.number()).required(),
});
-export interface ConditionInterface {
- schema: Joi.ObjectSchema;
- defaults: unknown;
- toObj: () => Record;
-}
-
-export class Condition implements ConditionInterface {
+// TODO: Consider turning this into an abstract class
+export class Condition {
+ // No schema by default, i.e. no validation by default
public readonly schema = Joi.object();
- public readonly defaults = {};
+ public readonly defaults: Record = {};
private validationError?: ValidationError;
constructor(private readonly value: Record = {}) {}
diff --git a/src/conditions/base/evm.ts b/src/conditions/base/evm.ts
index f1b47eb3f..c46659fc0 100644
--- a/src/conditions/base/evm.ts
+++ b/src/conditions/base/evm.ts
@@ -1,37 +1,29 @@
import Joi from 'joi';
-import {
- ETH_ADDRESS_REGEXP,
- SUPPORTED_CHAINS,
- USER_ADDRESS_PARAM,
-} from '../const';
-import { ContextParametersHandlerMixin } from '../context/mixin';
+import { ETH_ADDRESS_REGEXP, SUPPORTED_CHAINS } from '../const';
-import { Condition, makeReturnValueTest } from './condition';
+import { makeReturnValueTest } from './condition';
+import { RpcCondition } from './rpc';
export interface EvmConditionConfig {
CONDITION_TYPE: string;
STANDARD_CONTRACT_TYPES: string[];
METHODS_PER_CONTRACT_TYPE: Record;
PARAMETERS_PER_METHOD: Record;
- CONTEXT_PARAMETERS_PER_METHOD: Record;
}
+const METHODS_PER_CONTRACT_TYPE = {
+ ERC20: ['balanceOf'],
+ ERC721: ['balanceOf', 'ownerOf'],
+};
export const EvmConditionConfig: EvmConditionConfig = {
- CONDITION_TYPE: 'evm',
- STANDARD_CONTRACT_TYPES: ['ERC20', 'ERC721'],
- METHODS_PER_CONTRACT_TYPE: {
- ERC20: ['balanceOf'],
- ERC721: ['balanceOf', 'ownerOf'],
- },
+ CONDITION_TYPE: 'evm', // TODO: How is this used? Similar to the Timelock.defaults.method?
+ STANDARD_CONTRACT_TYPES: Object.keys(METHODS_PER_CONTRACT_TYPE),
+ METHODS_PER_CONTRACT_TYPE,
PARAMETERS_PER_METHOD: {
balanceOf: ['address'],
ownerOf: ['tokenId'],
},
- CONTEXT_PARAMETERS_PER_METHOD: {
- balanceOf: [USER_ADDRESS_PARAM],
- ownerOf: [USER_ADDRESS_PARAM],
- },
};
// A helper method for making complex Joi types
@@ -57,7 +49,7 @@ const makeMethod = () =>
'standardContractType'
);
-export class EvmConditionBase extends Condition {
+export class EvmCondition extends RpcCondition {
public readonly schema = Joi.object({
contractAddress: Joi.string().pattern(ETH_ADDRESS_REGEXP).required(),
chain: Joi.string()
@@ -74,9 +66,3 @@ export class EvmConditionBase extends Condition {
// At most one of these keys needs to be present
.xor('standardContractType', 'functionAbi');
}
-
-export const EvmCondition = ContextParametersHandlerMixin(EvmConditionBase);
-
-Object.defineProperty(EvmCondition.prototype, 'getContextConfig', {
- value: () => EvmConditionConfig.CONTEXT_PARAMETERS_PER_METHOD,
-});
diff --git a/src/conditions/base/rpc.ts b/src/conditions/base/rpc.ts
index 12dff4ab0..4cf9a3e6c 100644
--- a/src/conditions/base/rpc.ts
+++ b/src/conditions/base/rpc.ts
@@ -5,7 +5,6 @@ import {
SUPPORTED_CHAINS,
USER_ADDRESS_PARAM,
} from '../const';
-import { ContextParametersHandlerMixin } from '../context/mixin';
import { Condition, makeReturnValueTest } from './condition';
@@ -13,7 +12,6 @@ export interface RpcConditionConfig {
CONDITION_TYPE: string;
RPC_METHODS: string[];
PARAMETERS_PER_METHOD: Record;
- CONTEXT_PARAMETERS_PER_METHOD: Record;
}
export const RpcConditionConfig: RpcConditionConfig = {
@@ -23,15 +21,11 @@ export const RpcConditionConfig: RpcConditionConfig = {
eth_getBalance: ['address'],
balanceOf: ['address'],
},
- CONTEXT_PARAMETERS_PER_METHOD: {
- eth_getBalance: [USER_ADDRESS_PARAM],
- balanceOf: [USER_ADDRESS_PARAM],
- },
};
export const ethAddressOrUserAddress = Joi.alternatives().try(
Joi.string().pattern(ETH_ADDRESS_REGEXP),
- USER_ADDRESS_PARAM
+ USER_ADDRESS_PARAM,
);
export const getAddressSchema = () =>
@@ -46,10 +40,10 @@ export const rpcMethodSchema = RpcConditionConfig.RPC_METHODS.reduce(
}
return acc;
},
- {} as Record
+ {} as Record,
);
-export class RpcConditionBase extends Condition {
+export class RpcCondition extends Condition {
public readonly schema = Joi.object({
chain: Joi.number()
.valid(...SUPPORTED_CHAINS)
@@ -66,9 +60,3 @@ export class RpcConditionBase extends Condition {
returnValueTest: makeReturnValueTest(),
});
}
-
-export const RpcCondition = ContextParametersHandlerMixin(RpcConditionBase);
-
-Object.defineProperty(RpcCondition.prototype, 'getContextConfig', {
- value: () => RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD,
-});
diff --git a/src/conditions/base/timelock.ts b/src/conditions/base/timelock.ts
index fdf0b3574..ac00f6089 100644
--- a/src/conditions/base/timelock.ts
+++ b/src/conditions/base/timelock.ts
@@ -3,12 +3,16 @@ import Joi from 'joi';
import { Condition, makeReturnValueTest } from './condition';
export class TimelockCondition extends Condition {
+ // TODO: This is the only condition that uses defaults, and also the only condition that uses `method` in order
+ // to determine the schema. I.e. the only method that used `METHOD = 'timelock'` in `nucypher/nucypher`.
+ // TODO: Consider introducing a different field for this, e.g. `conditionType` or `type`. Use this field in a
+ // condition factory.
defaults = {
method: 'timelock',
};
public readonly schema = Joi.object({
+ method: Joi.string().valid(this.defaults.method).required(),
returnValueTest: makeReturnValueTest(),
- method: Joi.string().valid('timelock').required(),
});
}
diff --git a/src/conditions/context/context.ts b/src/conditions/context/context.ts
index 27d26b76f..95949962a 100644
--- a/src/conditions/context/context.ts
+++ b/src/conditions/context/context.ts
@@ -1,31 +1,36 @@
import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
-import { Eip712TypedData } from '../../web3';
import { USER_ADDRESS_PARAM } from '../const';
-import { WalletAuthenticationProvider } from './providers';
-
-interface TypedSignature {
- signature: string;
- typedData: Eip712TypedData;
- address: string;
-}
+import { TypedSignature, WalletAuthenticationProvider } from './providers';
export type CustomContextParam = string | number | boolean;
+export type ContextParam = CustomContextParam | TypedSignature;
-const SPECIAL_CONTEXT_PARAMS = [USER_ADDRESS_PARAM];
+const CONTEXT_PARAMS_HANDLERS = {
+ [USER_ADDRESS_PARAM]: async (
+ web3Provider: ethers.providers.Web3Provider
+ ): Promise => {
+ const provider = new WalletAuthenticationProvider(web3Provider);
+ return provider.getOrCreateWalletSignature();
+ },
+};
+export const RESERVED_CONTEXT_PARAMS = Object.keys(CONTEXT_PARAMS_HANDLERS);
+export const CONTEXT_PARAM_PREFIX = ':';
export class ConditionContext {
private readonly walletAuthProvider: WalletAuthenticationProvider;
constructor(
private readonly conditions: WASMConditions,
+ // TODO: We don't always need a web3 provider, only in cases where some specific context parameters are used
+ // TODO: Consider making this optional or introducing a different pattern to handle that
private readonly web3Provider: ethers.providers.Web3Provider,
public readonly customParameters: Record = {}
) {
Object.keys(customParameters).forEach((key) => {
- if (SPECIAL_CONTEXT_PARAMS.includes(key)) {
+ if (RESERVED_CONTEXT_PARAMS.includes(key)) {
throw new Error(
`Cannot use reserved parameter name ${key} as custom parameter`
);
@@ -34,30 +39,63 @@ export class ConditionContext {
this.walletAuthProvider = new WalletAuthenticationProvider(web3Provider);
}
- public toJson = async (): Promise => {
- const payload: Record = {};
- if (this.conditions.toString().includes(USER_ADDRESS_PARAM)) {
- payload[USER_ADDRESS_PARAM] =
- await this.walletAuthProvider.getOrCreateWalletSignature();
- }
+ public toObj = async (): Promise> => {
+ // First, we want to find all the parameters we need to add
+ const requestedParameters = new Set();
+ // Search conditions for parameters
const parsedConditions = JSON.parse(this.conditions.toString());
for (const cond of parsedConditions) {
- for (const key of cond.parameters) {
+ // Check return value test
+ const rvt = cond.returnValueTest.value;
+ if (typeof rvt === 'string' && rvt.startsWith(CONTEXT_PARAM_PREFIX)) {
+ requestedParameters.add(rvt);
+ }
+
+ // Check condition parameters
+ for (const param of cond.parameters ?? []) {
if (
- !(key in this.customParameters) &&
- !SPECIAL_CONTEXT_PARAMS.includes(key)
+ typeof param === 'string' &&
+ param.startsWith(CONTEXT_PARAM_PREFIX)
) {
- throw new Error(`Missing custom context parameter ${key}`);
+ requestedParameters.add(param);
}
}
}
+ // Now, we can safely add all the parameters
+ const parameters: Record = {};
+
+ // Fill in predefined context parameters
+ if (requestedParameters.has(USER_ADDRESS_PARAM)) {
+ parameters[USER_ADDRESS_PARAM] =
+ await this.walletAuthProvider.getOrCreateWalletSignature();
+ // Remove from requested parameters
+ requestedParameters.delete(USER_ADDRESS_PARAM);
+ }
+
+ // Fill in custom parameters
for (const key in this.customParameters) {
- payload[key] = this.customParameters[key];
+ parameters[key] = this.customParameters[key];
+ }
+
+ // Ok, so at this point we should have all the parameters we need
+ // If we don't, we have a problem and we should throw
+ const missingParameters = Array.from(requestedParameters).filter(
+ (key) => !parameters[key]
+ );
+ if (missingParameters.length > 0) {
+ throw new Error(
+ `Missing custom context parameter(s): ${missingParameters.join(', ')}`
+ );
}
- return JSON.stringify(payload);
+ return parameters;
+ };
+
+ public toJson = async (): Promise => {
+ const parameters = await this.toObj();
+ return JSON.stringify(parameters);
};
public withCustomParams = (
diff --git a/src/conditions/context/mixin.ts b/src/conditions/context/mixin.ts
deleted file mode 100644
index 6d6d0ed66..000000000
--- a/src/conditions/context/mixin.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { ConditionInterface } from '../base/condition';
-
-// Disabling because mixin constructor requires any arguments
-// eslint-disable-next-line @typescript-eslint/no-explicit-any
-type Constructor = new (
- ...params: TParams
-) => TResult;
-
-export function ContextParametersHandlerMixin<
- TBase extends Constructor
->(Base: TBase) {
- return class extends Base {
- // Disabling because mixin constructor requires any arguments
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- constructor(...args: any[]) {
- super(...args);
- }
-
- public getContextParameters(): string[] {
- const asObject = this.toObj();
- const method = asObject['method'] as string;
- const parameters = (asObject['parameters'] ?? []) as string[];
- const context = this.getContextConfig()[method];
-
- const returnValueTest = asObject['returnValueTest'] as Record<
- string,
- string
- >;
- const maybeParams = [...(context ?? []), returnValueTest['value']];
- return parameters.filter((p) => maybeParams.includes(p));
- }
-
- public getContextConfig(): Record {
- // Empty configuration object by default
- return {};
- }
- };
-}
diff --git a/src/conditions/context/providers.ts b/src/conditions/context/providers.ts
index 1758fe323..9b8db518e 100644
--- a/src/conditions/context/providers.ts
+++ b/src/conditions/context/providers.ts
@@ -3,7 +3,7 @@ import { utils as ethersUtils } from 'ethers/lib/ethers';
import { Eip712TypedData, FormattedTypedData } from '../../web3';
-interface TypedSignature {
+export interface TypedSignature {
signature: string;
typedData: Eip712TypedData;
address: string;
diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts
index fd5356138..f444720af 100644
--- a/test/docs/cbd.test.ts
+++ b/test/docs/cbd.test.ts
@@ -3,6 +3,7 @@ import { providers } from 'ethers';
import { Cohort, conditions, SecretKey, Strategy } from '../../src';
import { Ursula } from '../../src/characters/porter';
+import { EvmCondition } from '../../src/conditions/base';
import { toBytes } from '../../src/utils';
import {
fakeUrsulas,
@@ -19,7 +20,6 @@ import {
const {
predefined: { ERC721Ownership },
ConditionSet,
- Condition,
} = conditions;
describe('Get Started (CBD PoC)', () => {
@@ -100,7 +100,7 @@ describe('Get Started (CBD PoC)', () => {
value: 3,
},
};
- const NFTBalance = new Condition(NFTBalanceConfig);
+ const NFTBalance = new EvmCondition(NFTBalanceConfig);
const encrypter = newDeployed.encrypter;
diff --git a/test/unit/conditions/base/condition.test.ts b/test/unit/conditions/base/condition.test.ts
index 77a1dfba3..af25c8dd8 100644
--- a/test/unit/conditions/base/condition.test.ts
+++ b/test/unit/conditions/base/condition.test.ts
@@ -1,21 +1,10 @@
-import {
- EvmCondition,
- EvmConditionConfig,
-} from '../../../../src/conditions/base/evm';
-import {
- RpcCondition,
- RpcConditionConfig,
-} from '../../../../src/conditions/base/rpc';
import { ERC721Balance } from '../../../../src/conditions/predefined';
-import {
- TEST_CHAIN_ID,
- TEST_CONTRACT_ADDR,
- testEvmConditionObj,
- testReturnValueTest,
- testRpcConditionObj,
-} from '../../testVariables';
+import { TEST_CHAIN_ID, TEST_CONTRACT_ADDR } from '../../testVariables';
describe('validation', () => {
+ // TODO: Consider:
+ // Use Condition here with returnTestValue schema
+ // Refactor returnTestValue to be the part of the Condition
const condition = new ERC721Balance();
let result = condition.validate({
contractAddress: TEST_CONTRACT_ADDR,
@@ -34,71 +23,12 @@ describe('validation', () => {
});
it('rejects on an invalid schema value', async () => {
- result = condition.validate({ chain: -1 });
+ result = condition.validate({
+ chain: -1,
+ contractAddress: TEST_CONTRACT_ADDR,
+ });
expect(result.error?.message).toEqual(
'"chain" must be one of [1, 5, 137, 80001]'
);
});
});
-
-describe('get context parameters from conditions', () => {
- describe('from rpc condition', () => {
- const methods = RpcConditionConfig.RPC_METHODS;
- methods.forEach((method) => {
- const contextParams =
- RpcConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[
- method as keyof RpcConditionConfig
- ];
- if (!contextParams) {
- return;
- }
- contextParams.forEach((contextParam) => {
- it(`gets ${contextParam} for method ${method}`, () => {
- const rpcCondition = new RpcCondition({
- ...testRpcConditionObj,
- method,
- parameters: [contextParam],
- returnValueTest: {
- ...testReturnValueTest,
- value: contextParam,
- },
- });
-
- const producedContextParam = rpcCondition.getContextParameters();
- expect(producedContextParam).toEqual([contextParam]);
- });
- });
- });
- });
-
- describe('from evm condition', () => {
- EvmConditionConfig.STANDARD_CONTRACT_TYPES.forEach((contractType) => {
- const methods =
- EvmConditionConfig.METHODS_PER_CONTRACT_TYPE[contractType];
- if (!methods) {
- return;
- }
- methods.forEach((method) => {
- const contextParams =
- EvmConditionConfig.CONTEXT_PARAMETERS_PER_METHOD[method];
- if (!contextParams) {
- return;
- }
- contextParams.forEach((contextParam) => {
- it(`gets ${contextParam} for method ${method}`, () => {
- const evmCondition = new EvmCondition({
- ...testEvmConditionObj,
- parameters: [contextParam],
- returnValueTest: {
- ...testReturnValueTest,
- value: contextParam,
- },
- });
- const producedContextParam = evmCondition.getContextParameters();
- expect(producedContextParam).toEqual([contextParam]);
- });
- });
- });
- });
- });
-});
diff --git a/test/unit/conditions/base/evm.test.ts b/test/unit/conditions/base/evm.test.ts
index a417c9b6f..786fc31d7 100644
--- a/test/unit/conditions/base/evm.test.ts
+++ b/test/unit/conditions/base/evm.test.ts
@@ -1,4 +1,5 @@
import { EvmCondition } from '../../../../src/conditions/base';
+import { EvmConditionConfig } from '../../../../src/conditions/base/evm';
import { testEvmConditionObj } from '../../testVariables';
describe('validation', () => {
@@ -68,3 +69,94 @@ describe('accepts either standardContractType or functionAbi but not both or non
);
});
});
+
+describe('standard contract types and methods', () => {
+ const methods = EvmConditionConfig.METHODS_PER_CONTRACT_TYPE;
+ const methods_per_contract_type = Object.keys(methods).map((key) =>
+ methods[key].flatMap((method) => [key, method])
+ );
+
+ test.each(methods_per_contract_type)(
+ 'accepts %s with method %s',
+ (standardContractType, method) => {
+ const evmConditionObj = {
+ ...testEvmConditionObj,
+ standardContractType,
+ method,
+ };
+ const evmCondition = new EvmCondition(evmConditionObj);
+ expect(evmCondition.toObj()).toEqual(evmConditionObj);
+ }
+ );
+
+ it('rejects non-standard contract type with method', () => {
+ const conditionObj = {
+ ...testEvmConditionObj,
+ standardContractType: 'fake_standard_contract_type',
+ method: 'fake_method',
+ };
+ const badEvmCondition = new EvmCondition(conditionObj);
+ expect(() => badEvmCondition.toObj()).toThrow(
+ '"standardContractType" must be one of [ERC20, ERC721]'
+ );
+ });
+});
+
+// TODO(#124)
+// it('accepts custom parameters in function abi methods', async () => {
+// throw new Error('Not implemented');
+// });
+
+// TODO(#124)
+// describe('supports custom function abi', () => {
+// const fakeFunctionAbi = {
+// name: 'myFunction',
+// type: 'function',
+// inputs: [
+// {
+// name: 'account',
+// type: 'address',
+// },
+// {
+// name: 'myCustomParam',
+// type: 'uint256',
+// },
+// ],
+// outputs: [
+// {
+// name: 'someValue',
+// type: 'uint256',
+// },
+// ],
+// };
+// const evmConditionObj = {
+// ...testEvmConditionObj,
+// functionAbi: fakeFunctionAbi,
+// method: 'myFunction',
+// parameters: [USER_ADDRESS_PARAM, ':customParam'],
+// returnValueTest: {
+// index: 0,
+// comparator: '==',
+// value: USER_ADDRESS_PARAM,
+// },
+// };
+// const evmCondition = new EvmCondition(evmConditionObj);
+// const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
+// const conditionSet = new ConditionSet([evmCondition]);
+// const conditionContext = new ConditionContext(
+// conditionSet.toWASMConditions(),
+// web3Provider
+// );
+// const myCustomParam = ':customParam';
+// const customParams: Record = {};
+// customParams[myCustomParam] = 1234;
+//
+// it('accepts custom function abi', async () => {
+// const asJson = await conditionContext
+// .withCustomParams(customParams)
+// .toJson();
+// expect(asJson).toBeDefined();
+// expect(asJson).toContain(USER_ADDRESS_PARAM);
+// expect(asJson).toContain(myCustomParam);
+// });
+// });
diff --git a/test/unit/conditions/context.test.ts b/test/unit/conditions/context.test.ts
index d26775f2e..1909a9548 100644
--- a/test/unit/conditions/context.test.ts
+++ b/test/unit/conditions/context.test.ts
@@ -1,16 +1,22 @@
import { SecretKey } from '@nucypher/nucypher-core';
import { CustomContextParam } from '../../../src';
-import { ConditionContext, ConditionSet } from '../../../src/conditions';
+import { ConditionSet } from '../../../src/conditions';
import { EvmCondition, RpcCondition } from '../../../src/conditions/base';
import { USER_ADDRESS_PARAM } from '../../../src/conditions/const';
+import { RESERVED_CONTEXT_PARAMS } from '../../../src/conditions/context/context';
import { fakeWeb3Provider } from '../../utils';
-import { testEvmConditionObj, testRpcConditionObj } from '../testVariables';
+import {
+ testEvmConditionObj,
+ testFunctionAbi,
+ testReturnValueTest,
+ testRpcConditionObj,
+} from '../testVariables';
-describe('condition context', () => {
- it('should serialize to JSON with context params', async () => {
- const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
+const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
+describe('serialization', () => {
+ it('serializes to json', async () => {
const rpcCondition = new RpcCondition({
...testRpcConditionObj,
parameters: [USER_ADDRESS_PARAM],
@@ -20,133 +26,93 @@ describe('condition context', () => {
value: USER_ADDRESS_PARAM,
},
});
- const conditionSet = new ConditionSet([rpcCondition]);
-
- const conditionContext = new ConditionContext(
- conditionSet.toWASMConditions(),
+ const conditionContext = new ConditionSet([rpcCondition]).buildContext(
web3Provider
);
const asJson = await conditionContext.toJson();
- expect(asJson).toContain(USER_ADDRESS_PARAM);
+ expect(asJson).toBeDefined();
});
+});
- describe('supports user-defined parameters', () => {
- const evmConditionObj = {
- ...testEvmConditionObj,
- standardContractType: 'ERC20',
- method: 'balanceOf',
- parameters: [USER_ADDRESS_PARAM, ':customParam'],
- returnValueTest: {
- index: 0,
- comparator: '==',
- value: USER_ADDRESS_PARAM,
- },
- };
- const evmCondition = new EvmCondition(evmConditionObj);
- const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
- const conditionSet = new ConditionSet([evmCondition]);
- const conditionContext = new ConditionContext(
- conditionSet.toWASMConditions(),
- web3Provider
- );
- const myCustomParam = ':customParam';
- const customParams: Record = {};
- customParams[myCustomParam] = 1234;
+describe('context parameters', () => {
+ const customParamKey = ':customParam';
+ const customParams: Record = {};
+ customParams[customParamKey] = 1234;
- it('accepts user-provided context parameters', async () => {
- const asJson = await conditionContext
+ const evmConditionObj = {
+ ...testEvmConditionObj,
+ returnValueTest: {
+ ...testReturnValueTest,
+ value: customParamKey,
+ },
+ };
+ const evmCondition = new EvmCondition(evmConditionObj);
+ const conditionSet = new ConditionSet([evmCondition]);
+ const conditionContext = conditionSet.buildContext(web3Provider);
+
+ describe('return value test', () => {
+ it('accepts on a custom context parameters', async () => {
+ const asObj = await conditionContext
.withCustomParams(customParams)
- .toJson();
- expect(asJson).toBeDefined();
- expect(asJson).toContain(USER_ADDRESS_PARAM);
- expect(asJson).toContain(myCustomParam);
+ .toObj();
+ expect(asObj).toBeDefined();
+ expect(asObj[customParamKey]).toEqual(1234);
});
- it('throws on missing custom context param', async () => {
- await expect(conditionContext.toJson()).rejects.toThrow(
- `Missing custom context parameter ${myCustomParam}`
+ it('rejects on a missing custom context parameter', async () => {
+ await expect(conditionContext.toObj()).rejects.toThrow(
+ `Missing custom context parameter(s): ${customParamKey}`
);
});
+ });
- it('throws on using reserved context parameter identifiers', () => {
- const badCustomParams: Record = {};
- badCustomParams[USER_ADDRESS_PARAM] = 'this-will-throw';
-
+ it('rejects on using reserved context parameter', () => {
+ const badCustomParams: Record = {};
+ RESERVED_CONTEXT_PARAMS.forEach((reservedParam) => {
+ badCustomParams[reservedParam] = 'this-will-throw';
expect(() => conditionContext.withCustomParams(badCustomParams)).toThrow(
- `Cannot use reserved parameter name ${USER_ADDRESS_PARAM} as custom parameter`
+ `Cannot use reserved parameter name ${reservedParam} as custom parameter`
);
});
+ });
+
+ describe('custom method parameters', () => {
+ const evmConditionObj = {
+ ...testEvmConditionObj,
+ standardContractType: undefined,
+ functionAbi: testFunctionAbi,
+ parameters: [USER_ADDRESS_PARAM, customParamKey],
+ returnValueTest: {
+ ...testReturnValueTest,
+ },
+ };
- it('accepts custom parameters in predefined methods', async () => {
+ it('rejects on a missing parameter ', async () => {
const customEvmCondition = new EvmCondition({
...evmConditionObj,
- parameters: [myCustomParam],
+ parameters: [USER_ADDRESS_PARAM, customParamKey],
});
- const conditionSet = new ConditionSet([customEvmCondition]);
- const conditionContext = new ConditionContext(
- conditionSet.toWASMConditions(),
- web3Provider
+ const conditionContext = new ConditionSet([
+ customEvmCondition,
+ ]).buildContext(web3Provider);
+
+ await expect(async () => conditionContext.toObj()).rejects.toThrow(
+ `Missing custom context parameter(s): ${customParamKey}`
);
+ });
- const asJson = await conditionContext
- .withCustomParams(customParams)
- .toJson();
- expect(asJson).toBeDefined();
- expect(asJson).toContain(myCustomParam);
+ it('accepts on a hard-coded parameter ', async () => {
+ const customEvmCondition = new EvmCondition({
+ ...evmConditionObj,
+ parameters: [USER_ADDRESS_PARAM, 100],
+ });
+ const conditionContext = new ConditionSet([
+ customEvmCondition,
+ ]).buildContext(web3Provider);
+
+ const asObj = await conditionContext.toObj();
+ expect(asObj).toBeDefined();
+ expect(asObj[USER_ADDRESS_PARAM]).toBeDefined();
});
});
-
- // TODO: Fix this test. Fails with '"method" must be [balanceOf]'
- // describe('supports custom function abi', () => {
- // const fakeFunctionAbi = {
- // name: 'myFunction',
- // type: 'function',
- // inputs: [
- // {
- // name: 'account',
- // type: 'address',
- // },
- // {
- // name: 'myCustomParam',
- // type: 'uint256',
- // },
- // ],
- // outputs: [
- // {
- // name: 'someValue',
- // type: 'uint256',
- // },
- // ],
- // };
- // const evmConditionObj = {
- // ...testEvmConditionObj,
- // functionAbi: fakeFunctionAbi,
- // method: 'myFunction',
- // parameters: [USER_ADDRESS_PARAM, ':customParam'],
- // returnValueTest: {
- // index: 0,
- // comparator: '==',
- // value: USER_ADDRESS_PARAM,
- // },
- // };
- // const evmCondition = new EvmCondition(evmConditionObj);
- // const web3Provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
- // const conditionSet = new ConditionSet([evmCondition]);
- // const conditionContext = new ConditionContext(
- // conditionSet.toWASMConditions(),
- // web3Provider
- // );
- // const myCustomParam = ':customParam';
- // const customParams: Record = {};
- // customParams[myCustomParam] = 1234;
- //
- // it('accepts custom function abi', async () => {
- // const asJson = await conditionContext
- // .withCustomParams(customParams)
- // .toJson();
- // expect(asJson).toBeDefined();
- // expect(asJson).toContain(USER_ADDRESS_PARAM);
- // expect(asJson).toContain(myCustomParam);
- // });
- // });
});
diff --git a/test/unit/testVariables.ts b/test/unit/testVariables.ts
index f577291ef..13cad2210 100644
--- a/test/unit/testVariables.ts
+++ b/test/unit/testVariables.ts
@@ -90,3 +90,24 @@ export const testEvmConditionObj = {
parameters: ['0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77'],
returnValueTest: testReturnValueTest,
};
+
+export const testFunctionAbi = {
+ name: 'myFunction',
+ type: 'function',
+ inputs: [
+ {
+ name: 'account',
+ type: 'address',
+ },
+ {
+ name: 'myCustomParam',
+ type: 'uint256',
+ },
+ ],
+ outputs: [
+ {
+ name: 'someValue',
+ type: 'uint256',
+ },
+ ],
+};
From a0ea384ec813052c0fbab06e7f0644ebb105c089 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Mon, 15 May 2023 20:08:32 +0200
Subject: [PATCH 31/98] feat!: remove unused revocation kit
---
src/index.ts | 1 -
src/kits/revocation.ts | 10 ----------
2 files changed, 11 deletions(-)
delete mode 100644 src/kits/revocation.ts
diff --git a/src/index.ts b/src/index.ts
index 1b54d89cb..3087508d6 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -20,7 +20,6 @@ export type { Configuration } from './config';
export { defaultConfiguration } from './config';
// Kits
-export { RevocationKit } from './kits/revocation';
export { PolicyMessageKit } from './kits/message';
// Conditions
diff --git a/src/kits/revocation.ts b/src/kits/revocation.ts
deleted file mode 100644
index 9e34a77f0..000000000
--- a/src/kits/revocation.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { RevocationOrder, Signer, TreasureMap } from '@nucypher/nucypher-core';
-
-export class RevocationKit {
- public revocationOrder: RevocationOrder | null;
-
- // ideally underlying rust should throw an error if the treasure map is not signed by the signer
- constructor(treasureMap: TreasureMap, signer: Signer) {
- this.revocationOrder = treasureMap.makeRevocationOrders(signer);
- }
-}
From 96291e8c005c656713bc2a438111a2fedad3c544 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Tue, 16 May 2023 13:44:22 +0200
Subject: [PATCH 32/98] reworked evm condition validation
---
src/conditions/base/condition.ts | 19 -----
src/conditions/base/evm.ts | 109 ++++++++++++++------------
src/conditions/base/rpc.ts | 39 ++++-----
src/conditions/base/schema.ts | 35 +++++++++
src/conditions/base/timelock.ts | 3 +-
test/integration/pre.test.ts | 2 +
test/unit/conditions/base/evm.test.ts | 41 ++++++++--
7 files changed, 153 insertions(+), 95 deletions(-)
create mode 100644 src/conditions/base/schema.ts
diff --git a/src/conditions/base/condition.ts b/src/conditions/base/condition.ts
index f8711fba3..d6f5e5115 100644
--- a/src/conditions/base/condition.ts
+++ b/src/conditions/base/condition.ts
@@ -1,24 +1,5 @@
import Joi, { ValidationError } from 'joi';
-const COMPARATORS = ['==', '>', '<', '>=', '<=', '!='];
-
-export interface ReturnValueTestConfig {
- index?: number;
- comparator: string;
- value: string | number;
-}
-
-export const makeReturnValueTest =
- (): Joi.ObjectSchema =>
- Joi.object({
- index: Joi.number().optional(),
- comparator: Joi.string()
- .valid(...COMPARATORS)
- .required(),
- value: Joi.alternatives(Joi.string(), Joi.number()).required(),
- });
-
-// TODO: Consider turning this into an abstract class
export class Condition {
// No schema by default, i.e. no validation by default
public readonly schema = Joi.object();
diff --git a/src/conditions/base/evm.ts b/src/conditions/base/evm.ts
index c46659fc0..a0bf32594 100644
--- a/src/conditions/base/evm.ts
+++ b/src/conditions/base/evm.ts
@@ -1,68 +1,79 @@
import Joi from 'joi';
-import { ETH_ADDRESS_REGEXP, SUPPORTED_CHAINS } from '../const';
+import {
+ ETH_ADDRESS_REGEXP,
+ SUPPORTED_CHAINS,
+ USER_ADDRESS_PARAM,
+} from '../const';
-import { makeReturnValueTest } from './condition';
-import { RpcCondition } from './rpc';
+import { Condition } from './condition';
+import { makeReturnValueTest } from './schema';
-export interface EvmConditionConfig {
- CONDITION_TYPE: string;
- STANDARD_CONTRACT_TYPES: string[];
- METHODS_PER_CONTRACT_TYPE: Record;
- PARAMETERS_PER_METHOD: Record;
-}
-
-const METHODS_PER_CONTRACT_TYPE = {
- ERC20: ['balanceOf'],
- ERC721: ['balanceOf', 'ownerOf'],
-};
-export const EvmConditionConfig: EvmConditionConfig = {
- CONDITION_TYPE: 'evm', // TODO: How is this used? Similar to the Timelock.defaults.method?
- STANDARD_CONTRACT_TYPES: Object.keys(METHODS_PER_CONTRACT_TYPE),
- METHODS_PER_CONTRACT_TYPE,
- PARAMETERS_PER_METHOD: {
- balanceOf: ['address'],
- ownerOf: ['tokenId'],
- },
-};
+const standardContractMethods = Joi.string().when('standardContractType', {
+ switch: [
+ {
+ is: 'ERC20',
+ then: Joi.valid('balanceOf').required(),
+ },
+ {
+ is: 'ERC721',
+ then: Joi.valid('balanceOf', 'ownerOf').required(),
+ },
+ ],
+});
-// A helper method for making complex Joi types
-// It says "allow these `types` when `parent` value is given"
-const makeWhenGuard = (
- schema: Joi.StringSchema | Joi.ArraySchema,
- types: Record,
- parent: string
-) => {
- Object.entries(types).forEach(([key, value]) => {
- schema = schema.when(parent, {
- is: key,
- then: value,
- });
- });
- return schema;
-};
+const standardContractParameters = Joi.when('method', {
+ switch: [
+ {
+ is: 'balanceOf',
+ then: Joi.array()
+ .length(1)
+ .items(
+ Joi.alternatives(
+ Joi.string().pattern(ETH_ADDRESS_REGEXP),
+ Joi.string().equal(USER_ADDRESS_PARAM)
+ )
+ ),
+ },
+ {
+ is: 'ownerOf',
+ then: Joi.array()
+ .length(1)
+ .items(Joi.alternatives(Joi.number().integer().positive())),
+ },
+ ],
+});
-const makeMethod = () =>
- makeWhenGuard(
- Joi.string(),
- EvmConditionConfig.METHODS_PER_CONTRACT_TYPE,
- 'standardContractType'
- );
-
-export class EvmCondition extends RpcCondition {
+export class EvmCondition extends Condition {
public readonly schema = Joi.object({
contractAddress: Joi.string().pattern(ETH_ADDRESS_REGEXP).required(),
chain: Joi.string()
.valid(...SUPPORTED_CHAINS)
.required(),
standardContractType: Joi.string()
- .valid(...EvmConditionConfig.STANDARD_CONTRACT_TYPES)
+ .valid(...['ERC20', 'ERC721'])
.optional(),
functionAbi: Joi.object().optional(),
- method: makeMethod().required(),
+ method: Joi.string().required(),
parameters: Joi.array().required(),
returnValueTest: makeReturnValueTest(),
})
// At most one of these keys needs to be present
- .xor('standardContractType', 'functionAbi');
+ .xor('standardContractType', 'functionAbi')
+ // When standardContractType is present:
+ .when('.standardContractType', {
+ is: Joi.exist(),
+ then: Joi.object({
+ method: standardContractMethods,
+ parameters: standardContractParameters,
+ }),
+ })
+ // When functionAbi is present:
+ .when('.functionAbi', {
+ is: Joi.exist(),
+ then: Joi.object({
+ method: Joi.string().required(),
+ parameters: Joi.array().required(),
+ }),
+ });
}
diff --git a/src/conditions/base/rpc.ts b/src/conditions/base/rpc.ts
index 4cf9a3e6c..bbddf1f6f 100644
--- a/src/conditions/base/rpc.ts
+++ b/src/conditions/base/rpc.ts
@@ -6,7 +6,8 @@ import {
USER_ADDRESS_PARAM,
} from '../const';
-import { Condition, makeReturnValueTest } from './condition';
+import { Condition } from './condition';
+import { makeReturnValueTest } from './schema';
export interface RpcConditionConfig {
CONDITION_TYPE: string;
@@ -25,23 +26,28 @@ export const RpcConditionConfig: RpcConditionConfig = {
export const ethAddressOrUserAddress = Joi.alternatives().try(
Joi.string().pattern(ETH_ADDRESS_REGEXP),
- USER_ADDRESS_PARAM,
+ USER_ADDRESS_PARAM
);
export const getAddressSchema = () =>
Joi.array().items(ethAddressOrUserAddress).required();
-export const rpcMethodSchema = RpcConditionConfig.RPC_METHODS.reduce(
- (acc, method) => {
- if (RpcConditionConfig.PARAMETERS_PER_METHOD[method].includes('address')) {
- acc[method] = getAddressSchema();
- } else {
- acc[method] = Joi.array().items(Joi.string()).required();
- }
- return acc;
- },
- {} as Record,
-);
+const rpcMethodSchema = RpcConditionConfig.RPC_METHODS.reduce((acc, method) => {
+ if (RpcConditionConfig.PARAMETERS_PER_METHOD[method].includes('address')) {
+ acc[method] = getAddressSchema();
+ } else {
+ acc[method] = Joi.array().items(Joi.string()).required();
+ }
+ return acc;
+}, {} as Record);
+
+const makeParameters = () =>
+ Joi.when('method', {
+ switch: RpcConditionConfig.RPC_METHODS.map((method) => ({
+ is: method,
+ then: rpcMethodSchema[method],
+ })),
+ });
export class RpcCondition extends Condition {
public readonly schema = Joi.object({
@@ -51,12 +57,7 @@ export class RpcCondition extends Condition {
method: Joi.string()
.valid(...RpcConditionConfig.RPC_METHODS)
.required(),
- parameters: Joi.when('method', {
- switch: RpcConditionConfig.RPC_METHODS.map((method) => ({
- is: method,
- then: rpcMethodSchema[method],
- })),
- }),
+ parameters: makeParameters(),
returnValueTest: makeReturnValueTest(),
});
}
diff --git a/src/conditions/base/schema.ts b/src/conditions/base/schema.ts
new file mode 100644
index 000000000..4f9bec4cc
--- /dev/null
+++ b/src/conditions/base/schema.ts
@@ -0,0 +1,35 @@
+import Joi from 'joi';
+
+const COMPARATORS = ['==', '>', '<', '>=', '<=', '!='];
+
+export interface ReturnValueTestConfig {
+ index?: number;
+ comparator: string;
+ value: string | number;
+}
+
+export const makeReturnValueTest =
+ (): Joi.ObjectSchema =>
+ Joi.object({
+ index: Joi.number().optional(),
+ comparator: Joi.string()
+ .valid(...COMPARATORS)
+ .required(),
+ value: Joi.alternatives(Joi.string(), Joi.number()).required(),
+ });
+
+// A helper method for making complex Joi types
+// It says "allow these `types` when `parent` value is given"
+export const makeWhenGuard = (
+ schema: Joi.StringSchema | Joi.ArraySchema,
+ types: Record,
+ parent: string
+) => {
+ Object.entries(types).forEach(([key, value]) => {
+ schema = schema.when(parent, {
+ is: key,
+ then: value,
+ });
+ });
+ return schema;
+};
diff --git a/src/conditions/base/timelock.ts b/src/conditions/base/timelock.ts
index ac00f6089..4a734ff01 100644
--- a/src/conditions/base/timelock.ts
+++ b/src/conditions/base/timelock.ts
@@ -1,6 +1,7 @@
import Joi from 'joi';
-import { Condition, makeReturnValueTest } from './condition';
+import { Condition } from './condition';
+import { makeReturnValueTest } from './schema';
export class TimelockCondition extends Condition {
// TODO: This is the only condition that uses defaults, and also the only condition that uses `method` in order
diff --git a/test/integration/pre.test.ts b/test/integration/pre.test.ts
index 3c6500d95..2501509cb 100644
--- a/test/integration/pre.test.ts
+++ b/test/integration/pre.test.ts
@@ -87,10 +87,12 @@ describe('proxy reencryption', () => {
const genuineUndead = new ERC721Ownership({
contractAddress: '0x209e639a0EC166Ac7a1A4bA41968fa967dB30221',
chain: 1,
+ parameters: [1],
});
const gnomePals = new ERC721Ownership({
contractAddress: '0x5dB11d7356aa4C0E85Aa5b255eC2B5F81De6d4dA',
chain: 1,
+ parameters: [1],
});
const conditionsSet = new ConditionSet([
genuineUndead,
diff --git a/test/unit/conditions/base/evm.test.ts b/test/unit/conditions/base/evm.test.ts
index 786fc31d7..e0b47c7c9 100644
--- a/test/unit/conditions/base/evm.test.ts
+++ b/test/unit/conditions/base/evm.test.ts
@@ -1,5 +1,4 @@
import { EvmCondition } from '../../../../src/conditions/base';
-import { EvmConditionConfig } from '../../../../src/conditions/base/evm';
import { testEvmConditionObj } from '../../testVariables';
describe('validation', () => {
@@ -70,14 +69,17 @@ describe('accepts either standardContractType or functionAbi but not both or non
});
});
-describe('standard contract types and methods', () => {
- const methods = EvmConditionConfig.METHODS_PER_CONTRACT_TYPE;
+describe('standard contracts', () => {
+ const methods: Record = {
+ ERC20: ['balanceOf'],
+ ERC721: ['balanceOf', 'ownerOf'],
+ };
const methods_per_contract_type = Object.keys(methods).map((key) =>
methods[key].flatMap((method) => [key, method])
);
test.each(methods_per_contract_type)(
- 'accepts %s with method %s',
+ 'accepts on %s with method %s',
(standardContractType, method) => {
const evmConditionObj = {
...testEvmConditionObj,
@@ -89,17 +91,42 @@ describe('standard contract types and methods', () => {
}
);
- it('rejects non-standard contract type with method', () => {
- const conditionObj = {
+ it('rejects on a non-standard contract type with method', () => {
+ const badConditionObj = {
...testEvmConditionObj,
standardContractType: 'fake_standard_contract_type',
method: 'fake_method',
};
- const badEvmCondition = new EvmCondition(conditionObj);
+ const badEvmCondition = new EvmCondition(badConditionObj);
expect(() => badEvmCondition.toObj()).toThrow(
'"standardContractType" must be one of [ERC20, ERC721]'
);
});
+
+ it('rejects on a standard contract type with non-method', () => {
+ const badConditionObj = {
+ ...testEvmConditionObj,
+ standardContractType: 'ERC20',
+ method: 'fake_method',
+ };
+ const badEvmCondition = new EvmCondition(badConditionObj);
+ expect(() => badEvmCondition.toObj()).toThrow(
+ '"method" must be [balanceOf]'
+ );
+ });
+
+ it('rejects on a standard contract method with bad parameters', () => {
+ const badConditionObj = {
+ ...testEvmConditionObj,
+ standardContractType: 'ERC20',
+ method: 'balanceOf',
+ parameters: ['bad-address'],
+ };
+ const badEvmCondition = new EvmCondition(badConditionObj);
+ expect(() => badEvmCondition.toObj()).toThrow(
+ '"parameters[0]" with value "bad-address" fails to match the required pattern: /^0x[a-fA-F0-9]{40}$/'
+ );
+ });
});
// TODO(#124)
From 5bf6b74db7eb5c5de6f7938db0c0ace1e7a8c42f Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Tue, 16 May 2023 14:43:10 +0200
Subject: [PATCH 33/98] reworked rpc condition validation
---
src/conditions/base/evm.ts | 16 +++--------
src/conditions/base/rpc.ts | 51 +++++++----------------------------
src/conditions/base/schema.ts | 21 +++++----------
3 files changed, 20 insertions(+), 68 deletions(-)
diff --git a/src/conditions/base/evm.ts b/src/conditions/base/evm.ts
index a0bf32594..f4a562fd1 100644
--- a/src/conditions/base/evm.ts
+++ b/src/conditions/base/evm.ts
@@ -1,13 +1,9 @@
import Joi from 'joi';
-import {
- ETH_ADDRESS_REGEXP,
- SUPPORTED_CHAINS,
- USER_ADDRESS_PARAM,
-} from '../const';
+import { ETH_ADDRESS_REGEXP, SUPPORTED_CHAINS } from '../const';
import { Condition } from './condition';
-import { makeReturnValueTest } from './schema';
+import { ethAddressOrUserAddressSchema, makeReturnValueTest } from './schema';
const standardContractMethods = Joi.string().when('standardContractType', {
switch: [
@@ -28,12 +24,8 @@ const standardContractParameters = Joi.when('method', {
is: 'balanceOf',
then: Joi.array()
.length(1)
- .items(
- Joi.alternatives(
- Joi.string().pattern(ETH_ADDRESS_REGEXP),
- Joi.string().equal(USER_ADDRESS_PARAM)
- )
- ),
+ .items(ethAddressOrUserAddressSchema)
+ .required(),
},
{
is: 'ownerOf',
diff --git a/src/conditions/base/rpc.ts b/src/conditions/base/rpc.ts
index bbddf1f6f..b5ee34c21 100644
--- a/src/conditions/base/rpc.ts
+++ b/src/conditions/base/rpc.ts
@@ -1,51 +1,20 @@
-import Joi, { Schema } from 'joi';
+import Joi from 'joi';
-import {
- ETH_ADDRESS_REGEXP,
- SUPPORTED_CHAINS,
- USER_ADDRESS_PARAM,
-} from '../const';
+import { SUPPORTED_CHAINS } from '../const';
import { Condition } from './condition';
-import { makeReturnValueTest } from './schema';
+import { ethAddressOrUserAddressSchema, makeReturnValueTest } from './schema';
-export interface RpcConditionConfig {
- CONDITION_TYPE: string;
- RPC_METHODS: string[];
- PARAMETERS_PER_METHOD: Record;
-}
-
-export const RpcConditionConfig: RpcConditionConfig = {
- CONDITION_TYPE: 'rpc',
- RPC_METHODS: ['eth_getBalance', 'balanceOf'],
- PARAMETERS_PER_METHOD: {
- eth_getBalance: ['address'],
- balanceOf: ['address'],
- },
+const rpcMethodSchemas: Record = {
+ eth_getBalance: Joi.array().items(ethAddressOrUserAddressSchema).required(),
+ balanceOf: Joi.array().items(ethAddressOrUserAddressSchema).required(),
};
-export const ethAddressOrUserAddress = Joi.alternatives().try(
- Joi.string().pattern(ETH_ADDRESS_REGEXP),
- USER_ADDRESS_PARAM
-);
-
-export const getAddressSchema = () =>
- Joi.array().items(ethAddressOrUserAddress).required();
-
-const rpcMethodSchema = RpcConditionConfig.RPC_METHODS.reduce((acc, method) => {
- if (RpcConditionConfig.PARAMETERS_PER_METHOD[method].includes('address')) {
- acc[method] = getAddressSchema();
- } else {
- acc[method] = Joi.array().items(Joi.string()).required();
- }
- return acc;
-}, {} as Record);
-
const makeParameters = () =>
- Joi.when('method', {
- switch: RpcConditionConfig.RPC_METHODS.map((method) => ({
+ Joi.array().when('method', {
+ switch: Object.keys(rpcMethodSchemas).map((method) => ({
is: method,
- then: rpcMethodSchema[method],
+ then: rpcMethodSchemas[method],
})),
});
@@ -55,7 +24,7 @@ export class RpcCondition extends Condition {
.valid(...SUPPORTED_CHAINS)
.required(),
method: Joi.string()
- .valid(...RpcConditionConfig.RPC_METHODS)
+ .valid(...Object.keys(rpcMethodSchemas))
.required(),
parameters: makeParameters(),
returnValueTest: makeReturnValueTest(),
diff --git a/src/conditions/base/schema.ts b/src/conditions/base/schema.ts
index 4f9bec4cc..b2647cc93 100644
--- a/src/conditions/base/schema.ts
+++ b/src/conditions/base/schema.ts
@@ -1,5 +1,7 @@
import Joi from 'joi';
+import { ETH_ADDRESS_REGEXP, USER_ADDRESS_PARAM } from '../const';
+
const COMPARATORS = ['==', '>', '<', '>=', '<=', '!='];
export interface ReturnValueTestConfig {
@@ -18,18 +20,7 @@ export const makeReturnValueTest =
value: Joi.alternatives(Joi.string(), Joi.number()).required(),
});
-// A helper method for making complex Joi types
-// It says "allow these `types` when `parent` value is given"
-export const makeWhenGuard = (
- schema: Joi.StringSchema | Joi.ArraySchema,
- types: Record,
- parent: string
-) => {
- Object.entries(types).forEach(([key, value]) => {
- schema = schema.when(parent, {
- is: key,
- then: value,
- });
- });
- return schema;
-};
+export const ethAddressOrUserAddressSchema = Joi.alternatives().try(
+ Joi.string().pattern(ETH_ADDRESS_REGEXP),
+ USER_ADDRESS_PARAM
+);
From 278333ab5df48278fed2e0a111eac9623ef3988f Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Tue, 16 May 2023 15:51:28 +0200
Subject: [PATCH 34/98] self review
---
src/conditions/base/evm.ts | 4 ++--
src/conditions/base/rpc.ts | 4 ++--
src/conditions/base/schema.ts | 19 +++++++++----------
src/conditions/base/timelock.ts | 4 ++--
src/conditions/context/context.ts | 10 +---------
test/docs/cbd.test.ts | 2 +-
test/unit/conditions/base/evm.test.ts | 2 +-
test/unit/conditions/context.test.ts | 7 ++++---
8 files changed, 22 insertions(+), 30 deletions(-)
diff --git a/src/conditions/base/evm.ts b/src/conditions/base/evm.ts
index f4a562fd1..0e6b32810 100644
--- a/src/conditions/base/evm.ts
+++ b/src/conditions/base/evm.ts
@@ -3,7 +3,7 @@ import Joi from 'joi';
import { ETH_ADDRESS_REGEXP, SUPPORTED_CHAINS } from '../const';
import { Condition } from './condition';
-import { ethAddressOrUserAddressSchema, makeReturnValueTest } from './schema';
+import { ethAddressOrUserAddressSchema, returnValueTestSchema } from './schema';
const standardContractMethods = Joi.string().when('standardContractType', {
switch: [
@@ -48,7 +48,7 @@ export class EvmCondition extends Condition {
functionAbi: Joi.object().optional(),
method: Joi.string().required(),
parameters: Joi.array().required(),
- returnValueTest: makeReturnValueTest(),
+ returnValueTest: returnValueTestSchema,
})
// At most one of these keys needs to be present
.xor('standardContractType', 'functionAbi')
diff --git a/src/conditions/base/rpc.ts b/src/conditions/base/rpc.ts
index b5ee34c21..13d1edb33 100644
--- a/src/conditions/base/rpc.ts
+++ b/src/conditions/base/rpc.ts
@@ -3,7 +3,7 @@ import Joi from 'joi';
import { SUPPORTED_CHAINS } from '../const';
import { Condition } from './condition';
-import { ethAddressOrUserAddressSchema, makeReturnValueTest } from './schema';
+import { ethAddressOrUserAddressSchema, returnValueTestSchema } from './schema';
const rpcMethodSchemas: Record = {
eth_getBalance: Joi.array().items(ethAddressOrUserAddressSchema).required(),
@@ -27,6 +27,6 @@ export class RpcCondition extends Condition {
.valid(...Object.keys(rpcMethodSchemas))
.required(),
parameters: makeParameters(),
- returnValueTest: makeReturnValueTest(),
+ returnValueTest: returnValueTestSchema,
});
}
diff --git a/src/conditions/base/schema.ts b/src/conditions/base/schema.ts
index b2647cc93..62af41800 100644
--- a/src/conditions/base/schema.ts
+++ b/src/conditions/base/schema.ts
@@ -10,17 +10,16 @@ export interface ReturnValueTestConfig {
value: string | number;
}
-export const makeReturnValueTest =
- (): Joi.ObjectSchema =>
- Joi.object({
- index: Joi.number().optional(),
- comparator: Joi.string()
- .valid(...COMPARATORS)
- .required(),
- value: Joi.alternatives(Joi.string(), Joi.number()).required(),
- });
+export const returnValueTestSchema: Joi.ObjectSchema =
+ Joi.object({
+ index: Joi.number().optional(),
+ comparator: Joi.string()
+ .valid(...COMPARATORS)
+ .required(),
+ value: Joi.alternatives(Joi.string(), Joi.number()).required(),
+ });
-export const ethAddressOrUserAddressSchema = Joi.alternatives().try(
+export const ethAddressOrUserAddressSchema = Joi.alternatives(
Joi.string().pattern(ETH_ADDRESS_REGEXP),
USER_ADDRESS_PARAM
);
diff --git a/src/conditions/base/timelock.ts b/src/conditions/base/timelock.ts
index 4a734ff01..a517835c2 100644
--- a/src/conditions/base/timelock.ts
+++ b/src/conditions/base/timelock.ts
@@ -1,7 +1,7 @@
import Joi from 'joi';
import { Condition } from './condition';
-import { makeReturnValueTest } from './schema';
+import { returnValueTestSchema } from './schema';
export class TimelockCondition extends Condition {
// TODO: This is the only condition that uses defaults, and also the only condition that uses `method` in order
@@ -14,6 +14,6 @@ export class TimelockCondition extends Condition {
public readonly schema = Joi.object({
method: Joi.string().valid(this.defaults.method).required(),
- returnValueTest: makeReturnValueTest(),
+ returnValueTest: returnValueTestSchema,
});
}
diff --git a/src/conditions/context/context.ts b/src/conditions/context/context.ts
index 95949962a..91547d8d8 100644
--- a/src/conditions/context/context.ts
+++ b/src/conditions/context/context.ts
@@ -8,15 +8,7 @@ import { TypedSignature, WalletAuthenticationProvider } from './providers';
export type CustomContextParam = string | number | boolean;
export type ContextParam = CustomContextParam | TypedSignature;
-const CONTEXT_PARAMS_HANDLERS = {
- [USER_ADDRESS_PARAM]: async (
- web3Provider: ethers.providers.Web3Provider
- ): Promise => {
- const provider = new WalletAuthenticationProvider(web3Provider);
- return provider.getOrCreateWalletSignature();
- },
-};
-export const RESERVED_CONTEXT_PARAMS = Object.keys(CONTEXT_PARAMS_HANDLERS);
+export const RESERVED_CONTEXT_PARAMS = [USER_ADDRESS_PARAM];
export const CONTEXT_PARAM_PREFIX = ':';
export class ConditionContext {
diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts
index f444720af..934bb2985 100644
--- a/test/docs/cbd.test.ts
+++ b/test/docs/cbd.test.ts
@@ -3,7 +3,6 @@ import { providers } from 'ethers';
import { Cohort, conditions, SecretKey, Strategy } from '../../src';
import { Ursula } from '../../src/characters/porter';
-import { EvmCondition } from '../../src/conditions/base';
import { toBytes } from '../../src/utils';
import {
fakeUrsulas,
@@ -19,6 +18,7 @@ import {
const {
predefined: { ERC721Ownership },
+ base: { EvmCondition },
ConditionSet,
} = conditions;
diff --git a/test/unit/conditions/base/evm.test.ts b/test/unit/conditions/base/evm.test.ts
index e0b47c7c9..2ed5331e6 100644
--- a/test/unit/conditions/base/evm.test.ts
+++ b/test/unit/conditions/base/evm.test.ts
@@ -95,7 +95,7 @@ describe('standard contracts', () => {
const badConditionObj = {
...testEvmConditionObj,
standardContractType: 'fake_standard_contract_type',
- method: 'fake_method',
+ method: 'ownerOf',
};
const badEvmCondition = new EvmCondition(badConditionObj);
expect(() => badEvmCondition.toObj()).toThrow(
diff --git a/test/unit/conditions/context.test.ts b/test/unit/conditions/context.test.ts
index 1909a9548..9a1746919 100644
--- a/test/unit/conditions/context.test.ts
+++ b/test/unit/conditions/context.test.ts
@@ -31,6 +31,7 @@ describe('serialization', () => {
);
const asJson = await conditionContext.toJson();
expect(asJson).toBeDefined();
+ expect(asJson).toContain(USER_ADDRESS_PARAM);
});
});
@@ -79,9 +80,9 @@ describe('context parameters', () => {
describe('custom method parameters', () => {
const evmConditionObj = {
...testEvmConditionObj,
- standardContractType: undefined,
+ standardContractType: undefined, // We're going to use a custom function ABI
functionAbi: testFunctionAbi,
- parameters: [USER_ADDRESS_PARAM, customParamKey],
+ parameters: [USER_ADDRESS_PARAM, customParamKey], // We're going to use a custom parameter
returnValueTest: {
...testReturnValueTest,
},
@@ -101,7 +102,7 @@ describe('context parameters', () => {
);
});
- it('accepts on a hard-coded parameter ', async () => {
+ it('accepts on a hard-coded parameter', async () => {
const customEvmCondition = new EvmCondition({
...evmConditionObj,
parameters: [USER_ADDRESS_PARAM, 100],
From 6c4d9a05ad2ac03ce21622e40a2ee1627724249d Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 17 May 2023 18:13:50 +0200
Subject: [PATCH 35/98] remove limitations on standard contract type methods
and params
---
src/conditions/base/evm.ts | 51 +----------------------
test/unit/conditions/base/evm.test.ts | 60 ---------------------------
2 files changed, 2 insertions(+), 109 deletions(-)
diff --git a/src/conditions/base/evm.ts b/src/conditions/base/evm.ts
index 0e6b32810..820ffefe3 100644
--- a/src/conditions/base/evm.ts
+++ b/src/conditions/base/evm.ts
@@ -3,38 +3,7 @@ import Joi from 'joi';
import { ETH_ADDRESS_REGEXP, SUPPORTED_CHAINS } from '../const';
import { Condition } from './condition';
-import { ethAddressOrUserAddressSchema, returnValueTestSchema } from './schema';
-
-const standardContractMethods = Joi.string().when('standardContractType', {
- switch: [
- {
- is: 'ERC20',
- then: Joi.valid('balanceOf').required(),
- },
- {
- is: 'ERC721',
- then: Joi.valid('balanceOf', 'ownerOf').required(),
- },
- ],
-});
-
-const standardContractParameters = Joi.when('method', {
- switch: [
- {
- is: 'balanceOf',
- then: Joi.array()
- .length(1)
- .items(ethAddressOrUserAddressSchema)
- .required(),
- },
- {
- is: 'ownerOf',
- then: Joi.array()
- .length(1)
- .items(Joi.alternatives(Joi.number().integer().positive())),
- },
- ],
-});
+import { returnValueTestSchema } from './schema';
export class EvmCondition extends Condition {
public readonly schema = Joi.object({
@@ -51,21 +20,5 @@ export class EvmCondition extends Condition {
returnValueTest: returnValueTestSchema,
})
// At most one of these keys needs to be present
- .xor('standardContractType', 'functionAbi')
- // When standardContractType is present:
- .when('.standardContractType', {
- is: Joi.exist(),
- then: Joi.object({
- method: standardContractMethods,
- parameters: standardContractParameters,
- }),
- })
- // When functionAbi is present:
- .when('.functionAbi', {
- is: Joi.exist(),
- then: Joi.object({
- method: Joi.string().required(),
- parameters: Joi.array().required(),
- }),
- });
+ .xor('standardContractType', 'functionAbi');
}
diff --git a/test/unit/conditions/base/evm.test.ts b/test/unit/conditions/base/evm.test.ts
index 2ed5331e6..ade286a4d 100644
--- a/test/unit/conditions/base/evm.test.ts
+++ b/test/unit/conditions/base/evm.test.ts
@@ -69,66 +69,6 @@ describe('accepts either standardContractType or functionAbi but not both or non
});
});
-describe('standard contracts', () => {
- const methods: Record = {
- ERC20: ['balanceOf'],
- ERC721: ['balanceOf', 'ownerOf'],
- };
- const methods_per_contract_type = Object.keys(methods).map((key) =>
- methods[key].flatMap((method) => [key, method])
- );
-
- test.each(methods_per_contract_type)(
- 'accepts on %s with method %s',
- (standardContractType, method) => {
- const evmConditionObj = {
- ...testEvmConditionObj,
- standardContractType,
- method,
- };
- const evmCondition = new EvmCondition(evmConditionObj);
- expect(evmCondition.toObj()).toEqual(evmConditionObj);
- }
- );
-
- it('rejects on a non-standard contract type with method', () => {
- const badConditionObj = {
- ...testEvmConditionObj,
- standardContractType: 'fake_standard_contract_type',
- method: 'ownerOf',
- };
- const badEvmCondition = new EvmCondition(badConditionObj);
- expect(() => badEvmCondition.toObj()).toThrow(
- '"standardContractType" must be one of [ERC20, ERC721]'
- );
- });
-
- it('rejects on a standard contract type with non-method', () => {
- const badConditionObj = {
- ...testEvmConditionObj,
- standardContractType: 'ERC20',
- method: 'fake_method',
- };
- const badEvmCondition = new EvmCondition(badConditionObj);
- expect(() => badEvmCondition.toObj()).toThrow(
- '"method" must be [balanceOf]'
- );
- });
-
- it('rejects on a standard contract method with bad parameters', () => {
- const badConditionObj = {
- ...testEvmConditionObj,
- standardContractType: 'ERC20',
- method: 'balanceOf',
- parameters: ['bad-address'],
- };
- const badEvmCondition = new EvmCondition(badConditionObj);
- expect(() => badEvmCondition.toObj()).toThrow(
- '"parameters[0]" with value "bad-address" fails to match the required pattern: /^0x[a-fA-F0-9]{40}$/'
- );
- });
-});
-
// TODO(#124)
// it('accepts custom parameters in function abi methods', async () => {
// throw new Error('Not implemented');
From a22cb9bfa9c11a1c33a32405ea589a52a162fef3 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 17 May 2023 18:23:20 +0200
Subject: [PATCH 36/98] address pr comments
---
src/conditions/base/schema.ts | 6 +++++-
src/conditions/context/context.ts | 5 +++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/conditions/base/schema.ts b/src/conditions/base/schema.ts
index 62af41800..544033cdc 100644
--- a/src/conditions/base/schema.ts
+++ b/src/conditions/base/schema.ts
@@ -16,7 +16,11 @@ export const returnValueTestSchema: Joi.ObjectSchema =
comparator: Joi.string()
.valid(...COMPARATORS)
.required(),
- value: Joi.alternatives(Joi.string(), Joi.number()).required(),
+ value: Joi.alternatives(
+ Joi.string(),
+ Joi.number(),
+ Joi.boolean()
+ ).required(),
});
export const ethAddressOrUserAddressSchema = Joi.alternatives(
diff --git a/src/conditions/context/context.ts b/src/conditions/context/context.ts
index 91547d8d8..8549de332 100644
--- a/src/conditions/context/context.ts
+++ b/src/conditions/context/context.ts
@@ -27,6 +27,11 @@ export class ConditionContext {
`Cannot use reserved parameter name ${key} as custom parameter`
);
}
+ if (!key.startsWith(CONTEXT_PARAM_PREFIX)) {
+ throw new Error(
+ `Custom parameter ${key} must start with ${CONTEXT_PARAM_PREFIX}`
+ );
+ }
});
this.walletAuthProvider = new WalletAuthenticationProvider(web3Provider);
}
From 5d08d7b0fc1991d1ca1564517bf76aed583fc67f Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 18 May 2023 19:55:06 +0200
Subject: [PATCH 37/98] address pr comments, part 2
---
src/conditions/base/condition.ts | 6 +++++-
src/conditions/base/evm.ts | 4 +++-
src/conditions/base/rpc.ts | 2 +-
src/conditions/base/timelock.ts | 2 +-
4 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/src/conditions/base/condition.ts b/src/conditions/base/condition.ts
index d6f5e5115..2f53249d7 100644
--- a/src/conditions/base/condition.ts
+++ b/src/conditions/base/condition.ts
@@ -1,9 +1,13 @@
import Joi, { ValidationError } from 'joi';
+import { returnValueTestSchema } from './schema';
+
export class Condition {
// No schema by default, i.e. no validation by default
public readonly schema = Joi.object();
- public readonly defaults: Record = {};
+ public readonly defaults: Record = {
+ returnValueTest: returnValueTestSchema.required(),
+ };
private validationError?: ValidationError;
constructor(private readonly value: Record = {}) {}
diff --git a/src/conditions/base/evm.ts b/src/conditions/base/evm.ts
index 820ffefe3..79e7dfac3 100644
--- a/src/conditions/base/evm.ts
+++ b/src/conditions/base/evm.ts
@@ -5,6 +5,8 @@ import { ETH_ADDRESS_REGEXP, SUPPORTED_CHAINS } from '../const';
import { Condition } from './condition';
import { returnValueTestSchema } from './schema';
+export const STANDARD_CONTRACT_TYPES = ['ERC20', 'ERC721'];
+
export class EvmCondition extends Condition {
public readonly schema = Joi.object({
contractAddress: Joi.string().pattern(ETH_ADDRESS_REGEXP).required(),
@@ -12,7 +14,7 @@ export class EvmCondition extends Condition {
.valid(...SUPPORTED_CHAINS)
.required(),
standardContractType: Joi.string()
- .valid(...['ERC20', 'ERC721'])
+ .valid(...STANDARD_CONTRACT_TYPES)
.optional(),
functionAbi: Joi.object().optional(),
method: Joi.string().required(),
diff --git a/src/conditions/base/rpc.ts b/src/conditions/base/rpc.ts
index 13d1edb33..5144c251f 100644
--- a/src/conditions/base/rpc.ts
+++ b/src/conditions/base/rpc.ts
@@ -27,6 +27,6 @@ export class RpcCondition extends Condition {
.valid(...Object.keys(rpcMethodSchemas))
.required(),
parameters: makeParameters(),
- returnValueTest: returnValueTestSchema,
+ returnValueTest: returnValueTestSchema.required(),
});
}
diff --git a/src/conditions/base/timelock.ts b/src/conditions/base/timelock.ts
index a517835c2..5565f14c0 100644
--- a/src/conditions/base/timelock.ts
+++ b/src/conditions/base/timelock.ts
@@ -14,6 +14,6 @@ export class TimelockCondition extends Condition {
public readonly schema = Joi.object({
method: Joi.string().valid(this.defaults.method).required(),
- returnValueTest: returnValueTestSchema,
+ returnValueTest: returnValueTestSchema.required(),
});
}
From 284df4a26cb6c512749d918e079052808c4335c4 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Mon, 29 May 2023 13:25:38 +0200
Subject: [PATCH 38/98] fix: struct deser
---
package.json | 4 +-
src/characters/universal-bob.ts | 27 ++-
src/conditions/base/condition.ts | 34 ++--
src/conditions/base/timelock.ts | 2 +-
src/conditions/condition-set.ts | 37 ++--
src/conditions/context/context.ts | 7 +-
src/conditions/operator.ts | 4 +
src/conditions/predefined/erc721.ts | 4 +-
src/sdk/cohort.ts | 5 +
src/sdk/strategy.ts | 71 ++++++--
src/utils.ts | 42 ++++-
test/integration/dkg-client.test.ts | 2 +-
test/unit/cohort.test.ts | 68 ++-----
test/unit/conditions/base/condition.test.ts | 43 ++++-
test/unit/conditions/base/evm.test.ts | 5 +-
test/unit/conditions/base/rpc.test.ts | 2 +-
test/unit/conditions/base/timelock.test.ts | 2 +-
test/unit/strategy.test.ts | 188 +++++++++-----------
test/utils.ts | 24 ++-
yarn.lock | 111 +++++++++++-
20 files changed, 444 insertions(+), 238 deletions(-)
diff --git a/package.json b/package.json
index 763ab07db..d1853adae 100644
--- a/package.json
+++ b/package.json
@@ -53,9 +53,10 @@
},
"dependencies": {
"@nucypher/nucypher-core": "^0.7.0",
- "ferveo-wasm": "^0.1.1",
"axios": "^0.21.1",
+ "deep-equal": "^2.2.1",
"ethers": "^5.4.1",
+ "ferveo-wasm": "^0.1.1",
"joi": "^17.7.0",
"qs": "^6.10.1"
},
@@ -64,6 +65,7 @@
"@babel/preset-env": "^7.15.6",
"@skypack/package-check": "^0.2.2",
"@typechain/ethers-v5": "^9.0.0",
+ "@types/deep-equal": "^1.0.1",
"@types/jest": "^26.0.24",
"@types/qs": "^6.9.7",
"@typescript-eslint/eslint-plugin": "^4.0.1",
diff --git a/src/characters/universal-bob.ts b/src/characters/universal-bob.ts
index 68c8bdfcd..5f4182cd7 100644
--- a/src/characters/universal-bob.ts
+++ b/src/characters/universal-bob.ts
@@ -8,11 +8,11 @@ import {
} from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
-import { ConditionSet } from '../conditions/condition-set';
+import { ConditionSet } from '../conditions';
import { Keyring } from '../keyring';
import { PolicyMessageKit } from '../kits/message';
import { RetrievalResult } from '../kits/retrieval';
-import { base64ToU8Receiver, u8ToBase64Replacer, zip } from '../utils';
+import { base64ToU8Receiver, bytesEquals, toJson, zip } from '../utils';
import { Porter } from './porter';
@@ -27,6 +27,7 @@ type decrypterJSON = {
export class tDecDecrypter {
private readonly porter: Porter;
private readonly keyring: Keyring;
+
// private readonly verifyingKey: Keyring;
constructor(
@@ -98,7 +99,7 @@ export class tDecDecrypter {
.reduce((acc: Record[], val) => acc.concat(val), []);
const conditionContext =
- ConditionSet.fromList(conditions).buildContext(provider);
+ ConditionSet.fromConditionList(conditions).buildContext(provider);
const policyMessageKits = messageKits.map((mk) =>
PolicyMessageKit.fromMessageKit(
@@ -149,7 +150,7 @@ export class tDecDecrypter {
}
public toJSON(): string {
- return JSON.stringify(this.toObj(), u8ToBase64Replacer);
+ return toJson(this.toObj());
}
private static fromObj({
@@ -172,4 +173,22 @@ export class tDecDecrypter {
const config = JSON.parse(json, base64ToU8Receiver);
return tDecDecrypter.fromObj(config);
}
+
+ public equals(other: tDecDecrypter): boolean {
+ return (
+ this.porter.porterUrl.toString() === other.porter.porterUrl.toString() &&
+ bytesEquals(
+ this.policyEncryptingKey.toCompressedBytes(),
+ other.policyEncryptingKey.toCompressedBytes()
+ ) &&
+ bytesEquals(
+ this.encryptedTreasureMap.toBytes(),
+ other.encryptedTreasureMap.toBytes()
+ ) &&
+ bytesEquals(
+ this.publisherVerifyingKey.toCompressedBytes(),
+ other.publisherVerifyingKey.toCompressedBytes()
+ )
+ );
+ }
}
diff --git a/src/conditions/base/condition.ts b/src/conditions/base/condition.ts
index 2f53249d7..ee9fa4d04 100644
--- a/src/conditions/base/condition.ts
+++ b/src/conditions/base/condition.ts
@@ -1,25 +1,28 @@
-import Joi, { ValidationError } from 'joi';
+import Joi from 'joi';
-import { returnValueTestSchema } from './schema';
+import { objectEquals } from '../../utils';
+
+type Map = Record;
export class Condition {
- // No schema by default, i.e. no validation by default
public readonly schema = Joi.object();
- public readonly defaults: Record = {
- returnValueTest: returnValueTestSchema.required(),
- };
- private validationError?: ValidationError;
+ public readonly defaults: Map = {};
constructor(private readonly value: Record = {}) {}
- public get error(): string | undefined {
- return this.validationError?.message;
+ public validate(override: Map = {}) {
+ const newValue = {
+ ...this.defaults,
+ ...this.value,
+ ...override,
+ };
+ return this.schema.validate(newValue);
}
- public toObj(): Record {
- const { error, value } = this.validate();
+ public toObj(): Map {
+ const { error, value } = this.validate(this.value);
if (error) {
- throw Error(error.message);
+ throw `Invalid condition: ${error.message}`;
}
return value;
}
@@ -28,13 +31,12 @@ export class Condition {
// We disable the eslint rule here because we have to pass args to the constructor
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this: new (...args: any[]) => T,
- obj: Record
+ obj: Map
): T {
return new this(obj);
}
- public validate(data: Record = {}) {
- const newValue = Object.assign(this.defaults, this.value, data);
- return this.schema.validate(newValue);
+ public equals(other: Condition) {
+ return objectEquals(this, other);
}
}
diff --git a/src/conditions/base/timelock.ts b/src/conditions/base/timelock.ts
index 5565f14c0..e347524fb 100644
--- a/src/conditions/base/timelock.ts
+++ b/src/conditions/base/timelock.ts
@@ -8,7 +8,7 @@ export class TimelockCondition extends Condition {
// to determine the schema. I.e. the only method that used `METHOD = 'timelock'` in `nucypher/nucypher`.
// TODO: Consider introducing a different field for this, e.g. `conditionType` or `type`. Use this field in a
// condition factory.
- defaults = {
+ public readonly defaults: Record = {
method: 'timelock',
};
diff --git a/src/conditions/condition-set.ts b/src/conditions/condition-set.ts
index 7864c6c6e..31361b3c3 100644
--- a/src/conditions/condition-set.ts
+++ b/src/conditions/condition-set.ts
@@ -1,12 +1,18 @@
import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
-import { Condition } from './base/condition';
+import { toJson } from '../utils';
+
+import { Condition } from './base';
import { ConditionContext } from './context';
import { Operator } from './operator';
type ConditionOrOperator = Condition | Operator;
+export type ConditionSetJSON = {
+ conditions: ({ operator: string } | Record)[];
+};
+
export class ConditionSet {
constructor(public readonly conditions: ReadonlyArray) {}
@@ -34,13 +40,24 @@ export class ConditionSet {
return true;
}
- public toList() {
- return this.conditions.map((cnd) => {
+ public toObj(): ConditionSetJSON {
+ const conditions = this.conditions.map((cnd) => {
return cnd.toObj();
});
+ return { conditions };
+ }
+
+ public static fromObj(obj: ConditionSetJSON): ConditionSet {
+ const conditions = obj.conditions.map((cnd) => {
+ if ('operator' in cnd) {
+ return Operator.fromObj(cnd as Record);
+ }
+ return Condition.fromObj(cnd);
+ });
+ return new ConditionSet(conditions);
}
- public static fromList(list: ReadonlyArray>) {
+ public static fromConditionList(list: ReadonlyArray>) {
return new ConditionSet(
list.map((ele: Record) => {
if ('operator' in ele) return Operator.fromObj(ele);
@@ -49,16 +66,16 @@ export class ConditionSet {
);
}
- public toJson() {
- return JSON.stringify(this.toList());
+ public toJson(): string {
+ return toJson(this.toObj());
}
- public static fromJSON(json: string) {
- return ConditionSet.fromList(JSON.parse(json));
+ public static fromJSON(json: string): ConditionSet {
+ return ConditionSet.fromObj(JSON.parse(json));
}
- public toWASMConditions() {
- return new WASMConditions(this.toJson());
+ public toWASMConditions(): WASMConditions {
+ return new WASMConditions(toJson(this.toObj()));
}
public buildContext(
diff --git a/src/conditions/context/context.ts b/src/conditions/context/context.ts
index 8549de332..02e7156a0 100644
--- a/src/conditions/context/context.ts
+++ b/src/conditions/context/context.ts
@@ -1,6 +1,7 @@
import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
+import { fromJson, toJson } from '../../utils';
import { USER_ADDRESS_PARAM } from '../const';
import { TypedSignature, WalletAuthenticationProvider } from './providers';
@@ -41,8 +42,8 @@ export class ConditionContext {
const requestedParameters = new Set();
// Search conditions for parameters
- const parsedConditions = JSON.parse(this.conditions.toString());
- for (const cond of parsedConditions) {
+ const { conditions } = fromJson(this.conditions.toString());
+ for (const cond of conditions) {
// Check return value test
const rvt = cond.returnValueTest.value;
if (typeof rvt === 'string' && rvt.startsWith(CONTEXT_PARAM_PREFIX)) {
@@ -92,7 +93,7 @@ export class ConditionContext {
public toJson = async (): Promise => {
const parameters = await this.toObj();
- return JSON.stringify(parameters);
+ return toJson(parameters);
};
public withCustomParams = (
diff --git a/src/conditions/operator.ts b/src/conditions/operator.ts
index 2ef39471c..0c96e36b3 100644
--- a/src/conditions/operator.ts
+++ b/src/conditions/operator.ts
@@ -19,4 +19,8 @@ export class Operator {
static fromObj(obj: Record) {
return new Operator(obj.operator);
}
+
+ public equals(other: Operator): boolean {
+ return this.operator === other.operator;
+ }
}
diff --git a/src/conditions/predefined/erc721.ts b/src/conditions/predefined/erc721.ts
index 211a0b11b..ef9f880f3 100644
--- a/src/conditions/predefined/erc721.ts
+++ b/src/conditions/predefined/erc721.ts
@@ -2,7 +2,7 @@ import { EvmCondition } from '../base';
import { USER_ADDRESS_PARAM } from '../const';
export class ERC721Ownership extends EvmCondition {
- readonly defaults = {
+ public readonly defaults = {
method: 'ownerOf',
parameters: [],
standardContractType: 'ERC721',
@@ -15,7 +15,7 @@ export class ERC721Ownership extends EvmCondition {
}
export class ERC721Balance extends EvmCondition {
- readonly defaults = {
+ public readonly defaults = {
method: 'balanceOf',
parameters: [USER_ADDRESS_PARAM],
standardContractType: 'ERC721',
diff --git a/src/sdk/cohort.ts b/src/sdk/cohort.ts
index 02bc45bd4..99f2831db 100644
--- a/src/sdk/cohort.ts
+++ b/src/sdk/cohort.ts
@@ -1,5 +1,6 @@
import { Porter } from '../characters/porter';
import { ChecksumAddress } from '../types';
+import { objectEquals } from '../utils';
export type CohortConfiguration = {
readonly threshold: number;
@@ -70,4 +71,8 @@ export class Cohort {
porterUri: this.configuration.porterUri,
};
}
+
+ public equals(other: Cohort): boolean {
+ return objectEquals(this, other);
+ }
}
diff --git a/src/sdk/strategy.ts b/src/sdk/strategy.ts
index 5facc86d2..e8626bcd3 100644
--- a/src/sdk/strategy.ts
+++ b/src/sdk/strategy.ts
@@ -10,9 +10,9 @@ import { Alice } from '../characters/alice';
import { Bob } from '../characters/bob';
import { Enrico } from '../characters/enrico';
import { tDecDecrypter } from '../characters/universal-bob';
-import { ConditionSet } from '../conditions/condition-set';
+import { ConditionSet, ConditionSetJSON } from '../conditions/condition-set';
import { EnactedPolicy, EnactedPolicyJSON } from '../policies/policy';
-import { base64ToU8Receiver, u8ToBase64Replacer } from '../utils';
+import { base64ToU8Receiver, bytesEquals, toJson } from '../utils';
import { Cohort, CohortJSON } from './cohort';
@@ -20,7 +20,7 @@ type StrategyJSON = {
cohort: CohortJSON;
aliceSecretKeyBytes: Uint8Array;
bobSecretKeyBytes: Uint8Array;
- conditionSet?: ConditionSet;
+ conditionSet?: ConditionSetJSON;
startDate: Date;
endDate: Date;
};
@@ -29,7 +29,7 @@ type DeployedStrategyJSON = {
policy: EnactedPolicyJSON;
cohortConfig: CohortJSON;
bobSecretKeyBytes: Uint8Array;
- conditionSet?: ConditionSet;
+ conditionSet?: ConditionSetJSON;
};
export class Strategy {
@@ -119,14 +119,16 @@ export class Strategy {
public static fromJSON(json: string) {
const config = JSON.parse(json, base64ToU8Receiver);
+ config.startDate = new Date(config.startDate);
+ config.endDate = new Date(config.endDate);
return Strategy.fromObj(config);
}
public toJSON() {
- return JSON.stringify(this.toObj(), u8ToBase64Replacer);
+ return toJson(this.toObj());
}
- private static fromObj({
+ public static fromObj({
cohort,
aliceSecretKeyBytes,
bobSecretKeyBytes,
@@ -138,9 +140,9 @@ export class Strategy {
Cohort.fromObj(cohort),
SecretKey.fromBEBytes(aliceSecretKeyBytes),
SecretKey.fromBEBytes(bobSecretKeyBytes),
- startDate,
- endDate,
- conditionSet
+ new Date(startDate),
+ new Date(endDate),
+ conditionSet ? ConditionSet.fromObj(conditionSet) : undefined
);
}
@@ -149,11 +151,30 @@ export class Strategy {
cohort: this.cohort.toObj(),
aliceSecretKeyBytes: this.aliceSecretKey.toBEBytes(),
bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
- conditionSet: this.conditionSet,
+ conditionSet: this.conditionSet ? this.conditionSet.toObj() : undefined,
startDate: this.startDate,
endDate: this.endDate,
};
}
+
+ public equals(other: Strategy) {
+ return (
+ this.cohort.equals(other.cohort) &&
+ // TODO: Add equality to WASM bindings
+ bytesEquals(
+ this.aliceSecretKey.toBEBytes(),
+ other.aliceSecretKey.toBEBytes()
+ ) &&
+ bytesEquals(
+ this.bobSecretKey.toBEBytes(),
+ other.bobSecretKey.toBEBytes()
+ ) &&
+ this.startDate.toString() === other.startDate.toString() &&
+ this.endDate.toString() === other.endDate.toString() &&
+ this.conditionSet?.toWASMConditions ===
+ other.conditionSet?.toWASMConditions
+ );
+ }
}
export class DeployedStrategy {
@@ -173,7 +194,7 @@ export class DeployedStrategy {
}
public toJSON() {
- return JSON.stringify(this.toObj(), u8ToBase64Replacer);
+ return toJson(this.toObj());
}
private static fromObj({
@@ -204,7 +225,15 @@ export class DeployedStrategy {
const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
const label = newPolicy.label;
const cohort = Cohort.fromObj(cohortConfig);
- const encrypter = new Enrico(newPolicy.policyKey, undefined, conditionSet);
+
+ const conditionSetOrUndefined = conditionSet
+ ? ConditionSet.fromObj(conditionSet)
+ : undefined;
+ const encrypter = new Enrico(
+ newPolicy.policyKey,
+ undefined,
+ conditionSetOrUndefined
+ );
const decrypter = new tDecDecrypter(
cohort.configuration.porterUri,
@@ -220,7 +249,7 @@ export class DeployedStrategy {
encrypter,
decrypter,
bobSecretKey,
- conditionSet
+ conditionSetOrUndefined
);
}
@@ -235,7 +264,21 @@ export class DeployedStrategy {
policy,
cohortConfig: this.cohort.toObj(),
bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
- conditionSet: this.conditionSet,
+ conditionSet: this.conditionSet?.toObj(),
};
}
+
+ public equals(other: DeployedStrategy) {
+ return (
+ this.label === other.label &&
+ this.cohort.equals(other.cohort) &&
+ bytesEquals(this.policy.id.toBytes(), other.policy.id.toBytes()) &&
+ this.policy.label === other.policy.label &&
+ this.policy.policyKey.equals(other.policy.policyKey) &&
+ bytesEquals(
+ this.policy.encryptedTreasureMap.toBytes(),
+ other.policy.encryptedTreasureMap.toBytes()
+ )
+ );
+ }
}
diff --git a/src/utils.ts b/src/utils.ts
index c000feba2..dcacd59aa 100644
--- a/src/utils.ts
+++ b/src/utils.ts
@@ -1,3 +1,5 @@
+import deepEqual from 'deep-equal';
+
export const toBytes = (str: string): Uint8Array =>
new TextEncoder().encode(str);
@@ -15,29 +17,53 @@ export const toBase64 = (bytes: Uint8Array): string =>
export const fromBase64 = (str: string): Uint8Array =>
Buffer.from(str, 'base64');
-export const base64ToU8Receiver = (
- _key: string,
- value: string | number | Uint8Array
-) => {
+export const base64ToU8Receiver = (_key: string, value: unknown) => {
if (typeof value === 'string' && value.startsWith('base64:')) {
return fromBase64(value.split('base64:')[1]);
}
return value;
};
-export const u8ToBase64Replacer = (
- _key: string,
- value: string | number | Uint8Array
-) => {
+const sortedReplacer = (_key: string, value: unknown) => {
+ if (value instanceof Object && !(value instanceof Array)) {
+ return Object.keys(value)
+ .sort()
+ .reduce((sorted: Record, key) => {
+ sorted[key] = (value as Record)[key];
+ return sorted;
+ }, {});
+ }
+
+ return value;
+};
+
+const u8ToBase64Replacer = (_key: string, value: unknown) => {
if (value instanceof Uint8Array) {
return `base64:${toBase64(value)}`;
}
return value;
};
+const sortedSerializingReplacer = (_key: string, value: unknown): unknown => {
+ const serializedValue = u8ToBase64Replacer(_key, value);
+ return sortedReplacer(_key, serializedValue);
+};
+
+export const toJson = (obj: unknown) =>
+ JSON.stringify(obj, sortedSerializingReplacer);
+
+export const fromJson = (json: string) => JSON.parse(json, base64ToU8Receiver);
+
export const zip = (
a: ReadonlyArray,
b: ReadonlyArray
): ReadonlyArray => a.map((k, i) => [k, b[i]]);
export const toEpoch = (date: Date) => (date.getTime() / 1000) | 0;
+
+export const bytesEquals = (first: Uint8Array, second: Uint8Array): boolean =>
+ first.length === second.length &&
+ first.every((value, index) => value === second[index]);
+
+export const objectEquals = (a: unknown, b: unknown): boolean =>
+ deepEqual(a, b, { strict: true });
diff --git a/test/integration/dkg-client.test.ts b/test/integration/dkg-client.test.ts
index 13a76aa82..c1d002086 100644
--- a/test/integration/dkg-client.test.ts
+++ b/test/integration/dkg-client.test.ts
@@ -42,6 +42,6 @@ describe('DkgClient', () => {
const dkgClient = new DkgClient(provider, ritualId);
const isValid = await dkgClient.verifyRitual();
- expect(isValid).toBe(true);
+ expect(isValid).toBeTruthy();
});
});
diff --git a/test/unit/cohort.test.ts b/test/unit/cohort.test.ts
index 80ca256eb..40ab18ee8 100644
--- a/test/unit/cohort.test.ts
+++ b/test/unit/cohort.test.ts
@@ -1,62 +1,26 @@
import { Cohort } from '../../src';
-import { fakeUrsulas, mockGetUrsulas } from '../utils';
+import { fakeUrsulas, makeCohort } from '../utils';
describe('Cohort', () => {
- it('can create Cohort from configuration', async () => {
- const mockedUrsulas = fakeUrsulas().slice(0, 3);
- const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
- const config = {
- threshold: 2,
- shares: 3,
- porterUri: 'https://_this.should.crash',
- };
- const testCohort = await Cohort.create(config);
-
- const expectedUrsulas = [
- '0x5cf1703a1c99a4b42eb056535840e93118177232',
- '0x7fff551249d223f723557a96a0e1a469c79cc934',
- '0x9c7c824239d3159327024459ad69bb215859bd25',
- ];
- expect(getUrsulasSpy).toHaveBeenCalled();
- expect(testCohort.ursulaAddresses).toEqual(expectedUrsulas);
+ it('creates a Cohort', async () => {
+ const cohort = await makeCohort(mockedUrsulas);
+ const expectedUrsulas = mockedUrsulas.map((u) => u.checksumAddress);
+ expect(cohort.ursulaAddresses).toEqual(expectedUrsulas);
});
- it('can export to JSON', async () => {
- const mockedUrsulas = fakeUrsulas().slice(0, 3);
- const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
- const config = {
- threshold: 2,
- shares: 3,
- porterUri: 'https://_this.should.crash',
- };
- const testCohort = await Cohort.create(config);
- const configJSON = testCohort.toJSON();
- const expectedJSON =
- '{"ursulaAddresses":["0x5cf1703a1c99a4b42eb056535840e93118177232","0x7fff551249d223f723557a96a0e1a469c79cc934","0x9c7c824239d3159327024459ad69bb215859bd25"],"threshold":2,"shares":3,"porterUri":"https://_this.should.crash"}';
- expect(getUrsulasSpy).toHaveBeenCalled();
- expect(configJSON).toEqual(expectedJSON);
+ it('serializes to a plain object', async () => {
+ const cohort = await makeCohort(mockedUrsulas);
+ const asObj = cohort.toObj();
+ const fromObj = Cohort.fromObj(asObj);
+ expect(fromObj).toEqual(cohort);
});
- it('can import from JSON', async () => {
- const mockedUrsulas = fakeUrsulas().slice(0, 3);
- const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
-
- const configJSON =
- '{"ursulaAddresses":["0x5cf1703a1c99a4b42eb056535840e93118177232","0x7fff551249d223f723557a96a0e1a469c79cc934","0x9c7c824239d3159327024459ad69bb215859bd25"],"threshold":2,"shares":3,"porterUri":"https://_this.should.crash"}';
- const testCohort = Cohort.fromJSON(configJSON);
- const expectedUrsulas = [
- '0x5cf1703a1c99a4b42eb056535840e93118177232',
- '0x7fff551249d223f723557a96a0e1a469c79cc934',
- '0x9c7c824239d3159327024459ad69bb215859bd25',
- ];
- const expectedConfiguration = {
- threshold: 2,
- shares: 3,
- porterUri: 'https://_this.should.crash',
- };
- expect(getUrsulasSpy).toHaveBeenCalled();
- expect(testCohort.ursulaAddresses).toEqual(expectedUrsulas);
- expect(testCohort.configuration).toEqual(expectedConfiguration);
+ it('serializes to JSON', async () => {
+ const cohort = await makeCohort(mockedUrsulas);
+ const asJson = cohort.toJSON();
+ const fromJson = Cohort.fromJSON(asJson);
+ expect(fromJson).toEqual(cohort);
});
});
diff --git a/test/unit/conditions/base/condition.test.ts b/test/unit/conditions/base/condition.test.ts
index af25c8dd8..0fe10d714 100644
--- a/test/unit/conditions/base/condition.test.ts
+++ b/test/unit/conditions/base/condition.test.ts
@@ -1,29 +1,41 @@
-import { ERC721Balance } from '../../../../src/conditions/predefined';
-import { TEST_CHAIN_ID, TEST_CONTRACT_ADDR } from '../../testVariables';
+import { EvmCondition } from '../../../../src/conditions/base';
+import {
+ ERC721Balance,
+ ERC721Ownership,
+} from '../../../../src/conditions/predefined';
+import {
+ TEST_CHAIN_ID,
+ TEST_CONTRACT_ADDR,
+ TEST_CONTRACT_ADDR_2,
+ testEvmConditionObj,
+} from '../../testVariables';
describe('validation', () => {
// TODO: Consider:
// Use Condition here with returnTestValue schema
// Refactor returnTestValue to be the part of the Condition
const condition = new ERC721Balance();
- let result = condition.validate({
- contractAddress: TEST_CONTRACT_ADDR,
- chain: TEST_CHAIN_ID,
- });
it('accepts a correct schema', async () => {
+ const result = condition.validate({
+ contractAddress: TEST_CONTRACT_ADDR,
+ chain: TEST_CHAIN_ID,
+ });
expect(result.error).toBeUndefined();
expect(result.value.contractAddress).toEqual(TEST_CONTRACT_ADDR);
});
it('updates on a valid schema value', async () => {
- result = condition.validate({ chain: TEST_CHAIN_ID });
+ const result = condition.validate({
+ chain: TEST_CHAIN_ID,
+ contractAddress: TEST_CONTRACT_ADDR_2,
+ });
expect(result.error).toBeUndefined();
expect(result.value.chain).toEqual(TEST_CHAIN_ID);
});
it('rejects on an invalid schema value', async () => {
- result = condition.validate({
+ const result = condition.validate({
chain: -1,
contractAddress: TEST_CONTRACT_ADDR,
});
@@ -32,3 +44,18 @@ describe('validation', () => {
);
});
});
+
+describe('serialization', () => {
+ it('serializes to a plain object', () => {
+ const evm = new EvmCondition(testEvmConditionObj);
+ expect(evm.toObj()).toEqual(testEvmConditionObj);
+ });
+
+ it('serializes predefined conditions', () => {
+ const evm = new ERC721Ownership(testEvmConditionObj);
+ expect(evm.toObj()).toEqual({
+ ...evm.defaults,
+ ...testEvmConditionObj,
+ });
+ });
+});
diff --git a/test/unit/conditions/base/evm.test.ts b/test/unit/conditions/base/evm.test.ts
index ade286a4d..5dbdd3224 100644
--- a/test/unit/conditions/base/evm.test.ts
+++ b/test/unit/conditions/base/evm.test.ts
@@ -14,7 +14,10 @@ describe('validation', () => {
contractAddress: undefined,
};
const badEvm = new EvmCondition(badEvmCondition);
- expect(() => badEvm.toObj()).toThrow('"contractAddress" is required');
+ expect(() => badEvm.toObj()).toThrow(
+ 'Invalid condition: "contractAddress" is required'
+ );
+
const { error } = badEvm.validate(badEvmCondition);
expect(error?.message).toEqual('"contractAddress" is required');
});
diff --git a/test/unit/conditions/base/rpc.test.ts b/test/unit/conditions/base/rpc.test.ts
index 3b8f3a652..4f50abbe8 100644
--- a/test/unit/conditions/base/rpc.test.ts
+++ b/test/unit/conditions/base/rpc.test.ts
@@ -16,7 +16,7 @@ describe('validation', () => {
const badRpc = new RpcCondition(badRpcObj);
expect(() => badRpc.toObj()).toThrow(
- '"method" must be one of [eth_getBalance, balanceOf]'
+ 'Invalid condition: "method" must be one of [eth_getBalance, balanceOf]'
);
const { error } = badRpc.validate(badRpcObj);
diff --git a/test/unit/conditions/base/timelock.test.ts b/test/unit/conditions/base/timelock.test.ts
index 5d04dc212..674b1700b 100644
--- a/test/unit/conditions/base/timelock.test.ts
+++ b/test/unit/conditions/base/timelock.test.ts
@@ -28,7 +28,7 @@ describe('validation', () => {
const badTimelock = new TimelockCondition(badTimelockObj);
expect(() => badTimelock.toObj()).toThrow(
- '"returnValueTest.comparator" must be one of [==, >, <, >=, <=, !=]'
+ 'Invalid condition: "returnValueTest.comparator" must be one of [==, >, <, >=, <=, !=]'
);
const { error } = badTimelock.validate(badTimelockObj);
diff --git a/test/unit/strategy.test.ts b/test/unit/strategy.test.ts
index 5881493c3..18b6bd0e0 100644
--- a/test/unit/strategy.test.ts
+++ b/test/unit/strategy.test.ts
@@ -5,7 +5,6 @@ import {
} from '@nucypher/nucypher-core';
import {
- Cohort,
conditions,
DeployedStrategy,
Strategy,
@@ -16,6 +15,7 @@ import { fromBase64, toBytes } from '../../src/utils';
import {
fakeUrsulas,
fakeWeb3Provider,
+ makeCohort,
mockEncryptTreasureMap,
mockGenerateKFrags,
mockGetUrsulas,
@@ -27,10 +27,8 @@ import {
import {
aliceSecretKeyBytes,
bobSecretKeyBytes,
- decrypterJSON,
deployedStrategyJSON,
encryptedTreasureMapBase64,
- strategyJSON,
} from './testVariables';
const {
@@ -38,106 +36,93 @@ const {
ConditionSet,
} = conditions;
-describe('Strategy', () => {
- const cohortConfig = {
- threshold: 2,
- shares: 3,
- porterUri: 'https://_this.should.crash',
- };
- const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
- const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
- const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
- Date.now = jest.fn(() => 1487076708000);
+// Shared test variables
+const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
+const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
+const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
+Date.now = jest.fn(() => 1487076708000);
+const ownsNFT = new ERC721Ownership({
+ contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
+ parameters: [3591],
+ chain: 5,
+});
+const conditionSet = new ConditionSet([ownsNFT]);
+const mockedUrsulas = fakeUrsulas().slice(0, 3);
+describe('Strategy', () => {
afterEach(() => {
jest.restoreAllMocks();
});
- it('can create Strategy from configuration', async () => {
- const mockedUrsulas = fakeUrsulas().slice(0, 3);
- const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
-
- const testCohort = await Cohort.create(cohortConfig);
- const testStrategy = Strategy.create(
- testCohort,
- undefined,
+ it('creates a Strategy', async () => {
+ const cohort = await makeCohort(mockedUrsulas);
+ const strategy = Strategy.create(
+ cohort,
+ conditionSet,
aliceSecretKey,
bobSecretKey
);
+ expect(strategy.cohort).toEqual(cohort);
+ });
- const expectedUrsulas = mockedUrsulas.map(
- (ursula) => ursula.checksumAddress
+ it('serializes to plain object', async () => {
+ const cohort = await makeCohort(mockedUrsulas);
+ const strategy = Strategy.create(
+ cohort,
+ conditionSet,
+ aliceSecretKey,
+ bobSecretKey
);
- expect(getUrsulasSpy).toHaveBeenCalled();
- expect(testStrategy.cohort.ursulaAddresses).toEqual(expectedUrsulas);
+ const asObject = strategy.toObj();
+ const fromObject = Strategy.fromObj(asObject);
+ expect(fromObject.equals(strategy)).toBeTruthy();
});
- it('can export to JSON', async () => {
- const mockedUrsulas = fakeUrsulas().slice(0, 3);
- const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
- const testCohort = await Cohort.create(cohortConfig);
- const testStrategy = Strategy.create(
- testCohort,
- undefined,
+ it('serializes to JSON', async () => {
+ const cohort = await makeCohort(mockedUrsulas);
+ const strategy = Strategy.create(
+ cohort,
+ conditionSet,
aliceSecretKey,
- bobSecretKey,
- new Date('2017-02-14T12:51:48.000Z'),
- new Date('2123-03-16T12:51:48.000Z')
+ bobSecretKey
);
- const configJSON = testStrategy.toJSON();
- expect(configJSON).toEqual(strategyJSON);
- expect(getUrsulasSpy).toHaveBeenCalled();
- });
-
- it('can import from JSON', async () => {
- const testStrategy = Strategy.fromJSON(strategyJSON);
- const expectedUrsulas = [
- '0x5cf1703a1c99a4b42eb056535840e93118177232',
- '0x7fff551249d223f723557a96a0e1a469c79cc934',
- '0x9c7c824239d3159327024459ad69bb215859bd25',
- ];
- expect(testStrategy.cohort.ursulaAddresses).toEqual(expectedUrsulas);
+ const asJson = strategy.toJSON();
+ const fromJSON = Strategy.fromJSON(asJson);
+ expect(fromJSON.equals(strategy)).toBeTruthy();
});
- it('can deploy and return DeployedStrategy', async () => {
+ it('deploys strategy', async () => {
const mockedUrsulas = fakeUrsulas().slice(0, 3);
- const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
const makeTreasureMapSpy = mockMakeTreasureMap();
const encryptTreasureMapSpy = mockEncryptTreasureMap();
- const testCohort = await Cohort.create(cohortConfig);
- const testStrategy = Strategy.create(testCohort, undefined, aliceSecretKey);
- const testDeployed = await testStrategy.deploy('test', aliceProvider);
- expect(getUrsulasSpy).toHaveBeenCalled();
+ const cohort = await makeCohort(mockedUrsulas);
+ const strategy = Strategy.create(cohort, conditionSet, aliceSecretKey);
+ const label = 'test';
+
+ const deployedStrategy = await strategy.deploy(label, aliceProvider);
expect(generateKFragsSpy).toHaveBeenCalled();
expect(publishToBlockchainSpy).toHaveBeenCalled();
expect(encryptTreasureMapSpy).toHaveBeenCalled();
expect(makeTreasureMapSpy).toHaveBeenCalled();
- expect(testDeployed.label).toEqual('test');
+ expect(deployedStrategy.cohort).toEqual(cohort);
+ expect(deployedStrategy.conditionSet).toEqual(conditionSet);
+ expect(deployedStrategy.label).toEqual(label);
});
});
describe('Deployed Strategy', () => {
- const cohortConfig = {
- threshold: 2,
- shares: 3,
- porterUri: 'https://_this.should.crash',
- };
- const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
- const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
-
afterEach(() => {
jest.restoreAllMocks();
});
- it('can export to JSON', async () => {
+ it('serializes to JSON', async () => {
const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
const mockedUrsulas = fakeUrsulas().slice(0, 3);
- const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
const makeTreasureMapSpy = mockMakeTreasureMap();
@@ -145,33 +130,30 @@ describe('Deployed Strategy', () => {
EncryptedTreasureMap.fromBytes(fromBase64(encryptedTreasureMapBase64))
);
- const testCohort = await Cohort.create(cohortConfig);
- const testStrategy = Strategy.create(
- testCohort,
- undefined,
+ const cohort = await makeCohort(mockedUrsulas);
+ const strategy = Strategy.create(
+ cohort,
+ conditionSet,
aliceSecretKey,
- bobSecretKey,
- new Date('2017-02-14T12:51:48.000Z'),
- new Date('2123-03-16T12:51:48.000Z')
+ bobSecretKey
);
- const testDeployed = await testStrategy.deploy('test', aliceProvider);
- expect(getUrsulasSpy).toHaveBeenCalled();
+
+ const strategyAsJson = strategy.toJSON();
+ const strategyFromJson = Strategy.fromJSON(strategyAsJson);
+ expect(strategyFromJson.equals(strategy)).toBeTruthy();
+
+ const deployedStrategy = await strategy.deploy('test', aliceProvider);
expect(generateKFragsSpy).toHaveBeenCalled();
expect(publishToBlockchainSpy).toHaveBeenCalled();
expect(makeTreasureMapSpy).toHaveBeenCalled();
expect(encryptTreasureMapSpy).toHaveBeenCalled();
- const configJSON = testDeployed.toJSON();
- expect(configJSON).toEqual(deployedStrategyJSON);
- });
-
- it('can import from JSON', async () => {
- const importedStrategy = DeployedStrategy.fromJSON(deployedStrategyJSON);
- const configJSON = importedStrategy.toJSON();
- expect(configJSON).toEqual(deployedStrategyJSON);
+ const asJson = deployedStrategy.toJSON();
+ const fromJson = DeployedStrategy.fromJSON(asJson);
+ expect(fromJson.equals(deployedStrategy)).toBeTruthy();
});
- it('can encrypt and decrypt', async () => {
+ it('encrypts and decrypts', async () => {
const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
const bobProvider = fakeWeb3Provider(bobSecretKey.toBEBytes());
const mockedUrsulas = fakeUrsulas().slice(0, 3);
@@ -181,14 +163,14 @@ describe('Deployed Strategy', () => {
const makeTreasureMapSpy = mockMakeTreasureMap();
const encryptTreasureMapSpy = mockEncryptTreasureMap();
- const testCohort = await Cohort.create(cohortConfig);
- const testStrategy = Strategy.create(
- testCohort,
- undefined,
+ const cohort = await makeCohort(mockedUrsulas);
+ const strategy = Strategy.create(
+ cohort,
+ conditionSet,
aliceSecretKey,
bobSecretKey
);
- const testDeployed = await testStrategy.deploy('test', aliceProvider);
+ const deployedStrategy = await strategy.deploy('test', aliceProvider);
expect(getUrsulasSpy).toHaveBeenCalled();
expect(generateKFragsSpy).toHaveBeenCalled();
@@ -196,16 +178,11 @@ describe('Deployed Strategy', () => {
expect(encryptTreasureMapSpy).toHaveBeenCalled();
expect(makeTreasureMapSpy).toHaveBeenCalled();
- const encrypter = testDeployed.encrypter;
- const decrypter = testDeployed.decrypter;
+ const encrypter = deployedStrategy.encrypter;
+ const decrypter = deployedStrategy.decrypter;
- const ownsNFT = new ERC721Ownership({
- contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
- parameters: [3591],
- chain: 5,
- });
const plaintext = 'this is a secret';
- encrypter.conditions = new ConditionSet([ownsNFT]);
+ encrypter.conditions = conditionSet;
const encryptedMessageKit = encrypter.encryptMessage(plaintext);
// Setup mocks for `retrieveAndDecrypt`
@@ -228,20 +205,19 @@ describe('Deployed Strategy', () => {
expect(getUrsulasSpy2).toHaveBeenCalled();
expect(retrieveCFragsSpy).toHaveBeenCalled();
expect(decryptedMessage[0]).toEqual(toBytes(plaintext));
+
+ const serialized = deployedStrategy.toJSON();
+ const deserialized = DeployedStrategy.fromJSON(serialized);
+ expect(deserialized.equals(deployedStrategy)).toBeTruthy();
});
});
describe('tDecDecrypter', () => {
- const importedStrategy = DeployedStrategy.fromJSON(deployedStrategyJSON);
-
- it('can export to JSON', () => {
- const configJSON = importedStrategy.decrypter.toJSON();
- expect(configJSON).toEqual(decrypterJSON);
- });
+ const decrypter = DeployedStrategy.fromJSON(deployedStrategyJSON).decrypter;
- it('can import from JSON', () => {
- const decrypter = tDecDecrypter.fromJSON(decrypterJSON);
- const configJSON = decrypter.toJSON();
- expect(configJSON).toEqual(decrypterJSON);
+ it('serializes to JSON', () => {
+ const asJson = decrypter.toJSON();
+ const fromJson = tDecDecrypter.fromJSON(asJson);
+ expect(fromJson.equals(decrypter)).toBeTruthy();
});
});
diff --git a/test/utils.ts b/test/utils.ts
index b735af163..a0299b502 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -31,7 +31,7 @@ import {
ValidatorMessage,
} from 'ferveo-wasm';
-import { Alice, Bob, Configuration, RemoteBob } from '../src';
+import { Alice, Bob, Cohort, Configuration, RemoteBob } from '../src';
import { DkgParticipant, DkgRitual } from '../src/agents/coordinator';
import {
GetUrsulasResponse,
@@ -43,13 +43,13 @@ import { BlockchainPolicy, PreEnactedPolicy } from '../src/policies/policy';
import { ChecksumAddress } from '../src/types';
import { toBytes, toHexString, zip } from '../src/utils';
-export const fromBytes = (bytes: Uint8Array): string =>
- new TextDecoder().decode(bytes);
-
export const bytesEqual = (first: Uint8Array, second: Uint8Array): boolean =>
first.length === second.length &&
first.every((value, index) => value === second[index]);
+export const fromBytes = (bytes: Uint8Array): string =>
+ new TextDecoder().decode(bytes);
+
const mockConfig: Configuration = {
porterUri: 'https://_this_should_crash.com/',
};
@@ -273,11 +273,11 @@ const fakeDkgRitualE2e = (variant: 'precomputed' | 'simple') => {
const receivedMessages = messages.slice(0, threshold);
const serverAggregate = dkg.aggregateTranscript(receivedMessages);
- expect(serverAggregate.verify(sharesNum, receivedMessages)).toBe(true);
+ expect(serverAggregate.verify(sharesNum, receivedMessages)).toBeTruthy();
// Client can also aggregate the transcripts and verify them
const clientAggregate = new AggregatedTranscript(receivedMessages);
- expect(clientAggregate.verify(sharesNum, receivedMessages)).toBe(true);
+ expect(clientAggregate.verify(sharesNum, receivedMessages)).toBeTruthy();
// In the meantime, the client creates a ciphertext and decryption request
const msg = Buffer.from('my-msg');
@@ -388,3 +388,15 @@ export const fakeDkgParticipants = (): DkgParticipant[] => {
};
});
};
+
+export const makeCohort = async (ursulas: Ursula[]) => {
+ const getUrsulasSpy = mockGetUrsulas(ursulas);
+ const config = {
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ };
+ const cohort = await Cohort.create(config);
+ expect(getUrsulasSpy).toHaveBeenCalled();
+ return cohort;
+};
diff --git a/yarn.lock b/yarn.lock
index 4df504fb2..95d1fd5b1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1780,6 +1780,11 @@
dependencies:
"@babel/types" "^7.3.0"
+"@types/deep-equal@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@types/deep-equal/-/deep-equal-1.0.1.tgz#71cfabb247c22bcc16d536111f50c0ed12476b03"
+ integrity sha512-mMUu4nWHLBlHtxXY17Fg6+ucS/MnndyOWyOe7MmwkoMYxvfQU2ajtRaEvqSUv+aVkMqH/C0NCI8UoVfRNQ10yg==
+
"@types/graceful-fs@^4.1.2":
version "4.1.6"
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae"
@@ -2921,6 +2926,30 @@ dedent@0.7.0, dedent@^0.7.0:
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==
+deep-equal@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.1.tgz#c72ab22f3a7d3503a4ca87dde976fe9978816739"
+ integrity sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==
+ dependencies:
+ array-buffer-byte-length "^1.0.0"
+ call-bind "^1.0.2"
+ es-get-iterator "^1.1.3"
+ get-intrinsic "^1.2.0"
+ is-arguments "^1.1.1"
+ is-array-buffer "^3.0.2"
+ is-date-object "^1.0.5"
+ is-regex "^1.1.4"
+ is-shared-array-buffer "^1.0.2"
+ isarray "^2.0.5"
+ object-is "^1.1.5"
+ object-keys "^1.1.1"
+ object.assign "^4.1.4"
+ regexp.prototype.flags "^1.5.0"
+ side-channel "^1.0.4"
+ which-boxed-primitive "^1.0.2"
+ which-collection "^1.0.1"
+ which-typed-array "^1.1.9"
+
deep-extend@~0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
@@ -3116,6 +3145,21 @@ es-abstract@^1.19.0, es-abstract@^1.20.4:
unbox-primitive "^1.0.2"
which-typed-array "^1.1.9"
+es-get-iterator@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6"
+ integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.3"
+ has-symbols "^1.0.3"
+ is-arguments "^1.1.1"
+ is-map "^2.0.2"
+ is-set "^2.0.2"
+ is-string "^1.0.7"
+ isarray "^2.0.5"
+ stop-iteration-iterator "^1.0.0"
+
es-set-tostringtag@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
@@ -4124,7 +4168,7 @@ inquirer@8.2.5:
through "^2.3.6"
wrap-ansi "^7.0.0"
-internal-slot@^1.0.5:
+internal-slot@^1.0.4, internal-slot@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986"
integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==
@@ -4133,6 +4177,14 @@ internal-slot@^1.0.5:
has "^1.0.3"
side-channel "^1.0.4"
+is-arguments@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
+ integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
is-array-buffer@^3.0.1, is-array-buffer@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe"
@@ -4174,7 +4226,7 @@ is-core-module@^2.11.0, is-core-module@^2.5.0:
dependencies:
has "^1.0.3"
-is-date-object@^1.0.1:
+is-date-object@^1.0.1, is-date-object@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
@@ -4213,6 +4265,11 @@ is-interactive@^1.0.0:
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
+is-map@^2.0.1, is-map@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
+ integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==
+
is-negative-zero@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
@@ -4253,6 +4310,11 @@ is-regex@^1.1.4:
call-bind "^1.0.2"
has-tostringtag "^1.0.0"
+is-set@^2.0.1, is-set@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec"
+ integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==
+
is-shared-array-buffer@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
@@ -4312,6 +4374,11 @@ is-utf8@^0.2.1:
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==
+is-weakmap@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
+ integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
+
is-weakref@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
@@ -4319,6 +4386,14 @@ is-weakref@^1.0.2:
dependencies:
call-bind "^1.0.2"
+is-weakset@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d"
+ integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.1"
+
is-windows@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
@@ -4331,6 +4406,11 @@ is-wsl@^2.1.1:
dependencies:
is-docker "^2.0.0"
+isarray@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
+ integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
+
isarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
@@ -5391,6 +5471,14 @@ object-inspect@^1.12.3, object-inspect@^1.9.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
+object-is@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
+ integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+
object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
@@ -5876,7 +5964,7 @@ regenerator-transform@^0.15.1:
dependencies:
"@babel/runtime" "^7.8.4"
-regexp.prototype.flags@^1.4.3:
+regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb"
integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==
@@ -6223,6 +6311,13 @@ standard-version@^9.0.0:
stringify-package "^1.0.1"
yargs "^16.0.0"
+stop-iteration-iterator@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4"
+ integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==
+ dependencies:
+ internal-slot "^1.0.4"
+
string-format@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b"
@@ -6942,6 +7037,16 @@ which-boxed-primitive@^1.0.2:
is-string "^1.0.5"
is-symbol "^1.0.3"
+which-collection@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
+ integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==
+ dependencies:
+ is-map "^2.0.1"
+ is-set "^2.0.1"
+ is-weakmap "^2.0.1"
+ is-weakset "^2.0.1"
+
which-typed-array@^1.1.9:
version "1.1.9"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6"
From 76ac0f1ae56ffcf9bb8410f015f52e3af6c98af1 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Tue, 30 May 2023 10:44:44 +0200
Subject: [PATCH 39/98] feat: add class metadata to serialized conditions
---
src/conditions/base/condition.ts | 6 +++++-
test/unit/conditions/base/condition.test.ts | 6 +++++-
test/unit/conditions/base/evm.test.ts | 15 ++++++++++++---
test/unit/conditions/base/rpc.test.ts | 5 ++++-
test/unit/conditions/base/timelock.test.ts | 1 +
5 files changed, 27 insertions(+), 6 deletions(-)
diff --git a/src/conditions/base/condition.ts b/src/conditions/base/condition.ts
index ee9fa4d04..16c8c95ec 100644
--- a/src/conditions/base/condition.ts
+++ b/src/conditions/base/condition.ts
@@ -24,7 +24,10 @@ export class Condition {
if (error) {
throw `Invalid condition: ${error.message}`;
}
- return value;
+ return {
+ ...value,
+ _class: this.constructor.name,
+ };
}
public static fromObj(
@@ -33,6 +36,7 @@ export class Condition {
this: new (...args: any[]) => T,
obj: Map
): T {
+ delete obj._class;
return new this(obj);
}
diff --git a/test/unit/conditions/base/condition.test.ts b/test/unit/conditions/base/condition.test.ts
index 0fe10d714..a38798744 100644
--- a/test/unit/conditions/base/condition.test.ts
+++ b/test/unit/conditions/base/condition.test.ts
@@ -48,7 +48,10 @@ describe('validation', () => {
describe('serialization', () => {
it('serializes to a plain object', () => {
const evm = new EvmCondition(testEvmConditionObj);
- expect(evm.toObj()).toEqual(testEvmConditionObj);
+ expect(evm.toObj()).toEqual({
+ ...testEvmConditionObj,
+ _class: 'EvmCondition',
+ });
});
it('serializes predefined conditions', () => {
@@ -56,6 +59,7 @@ describe('serialization', () => {
expect(evm.toObj()).toEqual({
...evm.defaults,
...testEvmConditionObj,
+ _class: 'ERC721Ownership',
});
});
});
diff --git a/test/unit/conditions/base/evm.test.ts b/test/unit/conditions/base/evm.test.ts
index 5dbdd3224..5a35efa93 100644
--- a/test/unit/conditions/base/evm.test.ts
+++ b/test/unit/conditions/base/evm.test.ts
@@ -4,7 +4,10 @@ import { testEvmConditionObj } from '../../testVariables';
describe('validation', () => {
it('accepts on a valid schema', () => {
const evm = new EvmCondition(testEvmConditionObj);
- expect(evm.toObj()).toEqual(testEvmConditionObj);
+ expect(evm.toObj()).toEqual({
+ ...testEvmConditionObj,
+ _class: 'EvmCondition',
+ });
});
it('rejects an invalid schema', () => {
@@ -34,7 +37,10 @@ describe('accepts either standardContractType or functionAbi but not both or non
functionAbi: undefined,
};
const evmCondition = new EvmCondition(conditionObj);
- expect(evmCondition.toObj()).toEqual(conditionObj);
+ expect(evmCondition.toObj()).toEqual({
+ ...conditionObj,
+ _class: 'EvmCondition',
+ });
});
it('accepts functionAbi', () => {
@@ -44,7 +50,10 @@ describe('accepts either standardContractType or functionAbi but not both or non
standardContractType: undefined,
};
const evmCondition = new EvmCondition(conditionObj);
- expect(evmCondition.toObj()).toEqual(conditionObj);
+ expect(evmCondition.toObj()).toEqual({
+ ...conditionObj,
+ _class: 'EvmCondition',
+ });
});
it('rejects both', () => {
diff --git a/test/unit/conditions/base/rpc.test.ts b/test/unit/conditions/base/rpc.test.ts
index 4f50abbe8..8803854cf 100644
--- a/test/unit/conditions/base/rpc.test.ts
+++ b/test/unit/conditions/base/rpc.test.ts
@@ -4,7 +4,10 @@ import { testRpcConditionObj } from '../../testVariables';
describe('validation', () => {
it('accepts on a valid schema', () => {
const rpc = new RpcCondition(testRpcConditionObj);
- expect(rpc.toObj()).toEqual(testRpcConditionObj);
+ expect(rpc.toObj()).toEqual({
+ ...testRpcConditionObj,
+ _class: 'RpcCondition',
+ });
});
it('rejects an invalid schema', () => {
diff --git a/test/unit/conditions/base/timelock.test.ts b/test/unit/conditions/base/timelock.test.ts
index 674b1700b..b0ecdc3ca 100644
--- a/test/unit/conditions/base/timelock.test.ts
+++ b/test/unit/conditions/base/timelock.test.ts
@@ -14,6 +14,7 @@ describe('validation', () => {
expect(timelock.toObj()).toEqual({
returnValueTest,
method: 'timelock',
+ _class: 'TimelockCondition',
});
});
From b6eb53e1422c099d8c663ea5a97d82c67bf41d36 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 17 May 2023 14:50:08 +0200
Subject: [PATCH 40/98] feat: add tdec endpoint to porter
---
src/characters/porter.ts | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/src/characters/porter.ts b/src/characters/porter.ts
index 2aa1d7b1c..4b67b99fd 100644
--- a/src/characters/porter.ts
+++ b/src/characters/porter.ts
@@ -2,7 +2,9 @@ import {
CapsuleFrag,
PublicKey,
RetrievalKit,
- TreasureMap,
+ ThresholdDecryptionRequest,
+ ThresholdDecryptionResponse,
+ TreasureMap
} from '@nucypher/nucypher-core';
import axios, { AxiosResponse } from 'axios';
import qs from 'qs';
@@ -64,6 +66,13 @@ export type RetrieveCFragsResponse = {
errors: Record;
};
+
+type PostDecryptRequest = Uint8Array;
+
+type PostDecryptResult = Uint8Array;
+
+
+
export class Porter {
readonly porterUrl: URL;
@@ -132,4 +141,15 @@ export class Porter {
return { cFrags, errors };
});
}
+
+ public async decrypt(
+ tDecRequest: ThresholdDecryptionRequest
+ ): Promise {
+ const data: PostDecryptRequest = tDecRequest.toBytes();
+ const resp: AxiosResponse = await axios.post(
+ new URL('/decrypt', this.porterUrl).toString(),
+ data
+ );
+ return ThresholdDecryptionResponse.fromBytes(resp.data);
+ }
}
From cb5068727961f98eb7f0187d0f315baf772ffa9f Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Thu, 18 May 2023 12:53:35 +0200
Subject: [PATCH 41/98] sketch a cbd flow with dkg
---
examples/api-example.ts | 2 +-
src/agents/coordinator.ts | 4 +-
src/characters/cbd-universal-bob.ts | 165 ++++++++++++++
src/characters/enrico.ts | 47 +++-
src/characters/porter.ts | 12 +-
...{universal-bob.ts => pre-universal-bob.ts} | 12 +-
src/dkg.ts | 56 ++++-
src/index.ts | 4 +-
src/sdk/strategy/cbd-strategy.ts | 160 ++++++++++++++
.../{strategy.ts => strategy/pre-strategy.ts} | 41 ++--
test/acceptance/alice-grants.test.ts | 2 +-
test/docs/cbd.test.ts | 6 +-
test/integration/dkg-client.test.ts | 15 +-
test/integration/enrico.test.ts | 8 +-
test/integration/pre.test.ts | 4 +-
test/unit/cbd-strategy.test.ts | 209 ++++++++++++++++++
...{strategy.test.ts => pre-strategy.test.ts} | 50 +++--
test/utils.ts | 46 +++-
18 files changed, 744 insertions(+), 99 deletions(-)
create mode 100644 src/characters/cbd-universal-bob.ts
rename src/characters/{universal-bob.ts => pre-universal-bob.ts} (96%)
create mode 100644 src/sdk/strategy/cbd-strategy.ts
rename src/sdk/{strategy.ts => strategy/pre-strategy.ts} (88%)
create mode 100644 test/unit/cbd-strategy.test.ts
rename test/unit/{strategy.test.ts => pre-strategy.test.ts} (83%)
diff --git a/examples/api-example.ts b/examples/api-example.ts
index 0df37e9ea..6ea4909d4 100644
--- a/examples/api-example.ts
+++ b/examples/api-example.ts
@@ -26,7 +26,7 @@ async function example() {
// Enrico encrypts data on behalf of Alice
const enrico = new Enrico(policy.policyKey);
const message = 'secret-message-from-alice';
- const encryptedMessage = enrico.encryptMessage(toBytes(message));
+ const encryptedMessage = enrico.encryptMessagePre(toBytes(message));
// Bob retrieves & decrypts encrypted message
const bob = fakeBob();
diff --git a/src/agents/coordinator.ts b/src/agents/coordinator.ts
index 159492ff9..f6fca8176 100644
--- a/src/agents/coordinator.ts
+++ b/src/agents/coordinator.ts
@@ -7,7 +7,7 @@ import {
import { getContract } from './contracts';
-export interface DkgRitual {
+export interface CoordinatorRitual {
id: number;
initiator: string;
dkgSize: number;
@@ -43,7 +43,7 @@ export class DkgCoordinatorAgent {
public static async getRitual(
provider: ethers.providers.Provider,
ritualId: number
- ): Promise {
+ ): Promise {
const Coordinator = await this.connectReadOnly(provider);
return await Coordinator.rituals(ritualId);
}
diff --git a/src/characters/cbd-universal-bob.ts b/src/characters/cbd-universal-bob.ts
new file mode 100644
index 000000000..2a1f96fc9
--- /dev/null
+++ b/src/characters/cbd-universal-bob.ts
@@ -0,0 +1,165 @@
+import {
+ Context,
+ MessageKit,
+ PublicKey,
+ SecretKey,
+ Signer,
+ ThresholdDecryptionRequest,
+} from '@nucypher/nucypher-core';
+import { ethers } from 'ethers';
+import {
+ combineDecryptionSharesPrecomputed,
+ combineDecryptionSharesSimple,
+ DecryptionSharePrecomputed,
+ DecryptionShareSimple,
+ decryptWithSharedSecret,
+ DkgPublicKey,
+} from 'ferveo-wasm';
+import { SharedSecret } from 'ferveo-wasm';
+import { Ciphertext } from 'ferveo-wasm';
+
+import { ConditionSet } from '../conditions';
+import { DkgRitual, FerveoVariant } from '../dkg';
+import { Keyring } from '../keyring';
+import { PolicyMessageKit } from '../kits/message';
+import { base64ToU8Receiver, u8ToBase64Replacer } from '../utils';
+
+import { Porter } from './porter';
+
+type CbdTDecDecrypterJSON = {
+ porterUri: string;
+ encryptingKeyBytes: Uint8Array;
+ bobSecretKeyBytes: Uint8Array;
+};
+
+export class CbdTDecDecrypter {
+ private readonly porter: Porter;
+ private readonly keyring: Keyring;
+
+ // private readonly verifyingKey: Keyring;
+
+ constructor(
+ porterUri: string,
+ private readonly dkgPublicKey: DkgPublicKey,
+ secretKey: SecretKey
+ ) {
+ this.porter = new Porter(porterUri);
+ this.keyring = new Keyring(secretKey);
+ }
+
+ public get decryptingKey(): PublicKey {
+ return this.keyring.publicKey;
+ }
+
+ public get signer(): Signer {
+ return this.keyring.signer;
+ }
+
+ public decrypt(messageKit: MessageKit | PolicyMessageKit): Uint8Array {
+ return this.keyring.decrypt(messageKit);
+ }
+
+ public async retrieveAndDecrypt(
+ provider: ethers.providers.Web3Provider,
+ conditionSet: ConditionSet,
+ dkgRitual: DkgRitual,
+ variant: number,
+ ciphertext: Ciphertext,
+ aad: Uint8Array
+ ): Promise {
+ const decryptionShares = await this.retrieve(
+ provider,
+ conditionSet,
+ dkgRitual.id,
+ variant,
+ ciphertext
+ );
+
+ // TODO: Replace with a factory method
+ let sharedSecret: SharedSecret;
+ if (variant === FerveoVariant.Simple) {
+ sharedSecret = combineDecryptionSharesSimple(
+ decryptionShares as DecryptionShareSimple[],
+ dkgRitual.dkgPublicParams
+ );
+ } else if (variant === FerveoVariant.Precomputed) {
+ sharedSecret = combineDecryptionSharesPrecomputed(
+ decryptionShares as DecryptionSharePrecomputed[]
+ );
+ } else {
+ throw new Error(`Unknown variant ${variant}`);
+ }
+
+ const plaintext = decryptWithSharedSecret(
+ ciphertext,
+ aad,
+ sharedSecret,
+ dkgRitual.dkgPublicParams
+ );
+ return [plaintext];
+ }
+
+ public async retrieve(
+ provider: ethers.providers.Web3Provider,
+ conditionSet: ConditionSet,
+ ritualId: number,
+ variant: number,
+ ciphertext: Ciphertext
+ ): Promise {
+ const contextStr = await conditionSet.buildContext(provider).toJson();
+
+ // TODO: Move ThresholdDecryptionRequest creation and parsing to Porter?
+ const tDecRequest = new ThresholdDecryptionRequest(
+ ritualId,
+ variant,
+ ciphertext.toBytes(),
+ conditionSet.toWASMConditions(),
+ new Context(contextStr)
+ );
+
+ // TODO: This should return multiple responses
+ const resp = await this.porter.decrypt(tDecRequest);
+
+ // TODO: Replace with a factory method
+ if (variant === FerveoVariant.Simple) {
+ return resp.map((r) =>
+ DecryptionShareSimple.fromBytes(r.decryptionShare)
+ );
+ } else if (variant === FerveoVariant.Precomputed) {
+ return resp.map((r) =>
+ DecryptionSharePrecomputed.fromBytes(r.decryptionShare)
+ );
+ } else {
+ throw new Error(`Unknown variant ${variant}`);
+ }
+ }
+
+ public toObj(): CbdTDecDecrypterJSON {
+ return {
+ porterUri: this.porter.porterUrl.toString(),
+ encryptingKeyBytes: this.dkgPublicKey.toBytes(),
+ bobSecretKeyBytes: this.keyring.secretKey.toBEBytes(),
+ };
+ }
+
+ public toJSON(): string {
+ return JSON.stringify(this.toObj(), u8ToBase64Replacer);
+ }
+
+ private static fromObj({
+ porterUri,
+ encryptingKeyBytes,
+ bobSecretKeyBytes,
+ }: CbdTDecDecrypterJSON) {
+ return new CbdTDecDecrypter(
+ porterUri,
+ DkgPublicKey.fromBytes(encryptingKeyBytes),
+ SecretKey.fromBEBytes(bobSecretKeyBytes)
+ );
+ }
+
+ public static fromJSON(json: string) {
+ const config = JSON.parse(json, base64ToU8Receiver);
+ return CbdTDecDecrypter.fromObj(config);
+ }
+}
diff --git a/src/characters/enrico.ts b/src/characters/enrico.ts
index cd8bed5bc..488b6ae33 100644
--- a/src/characters/enrico.ts
+++ b/src/characters/enrico.ts
@@ -1,20 +1,21 @@
import { MessageKit, PublicKey, SecretKey } from '@nucypher/nucypher-core';
+import { Ciphertext, DkgPublicKey, encrypt } from 'ferveo-wasm';
-import { ConditionSet } from '../conditions/condition-set';
+import { ConditionSet } from '../conditions';
import { Keyring } from '../keyring';
import { toBytes } from '../utils';
export class Enrico {
- public readonly policyEncryptingKey: PublicKey;
+ public readonly encryptingKey: PublicKey | DkgPublicKey;
private readonly keyring: Keyring;
public conditions?: ConditionSet;
constructor(
- policyEncryptingKey: PublicKey,
+ encryptingKey: PublicKey | DkgPublicKey,
verifyingKey?: SecretKey,
conditions?: ConditionSet
) {
- this.policyEncryptingKey = policyEncryptingKey;
+ this.encryptingKey = encryptingKey;
this.keyring = new Keyring(verifyingKey ?? SecretKey.random());
this.conditions = conditions;
}
@@ -23,17 +24,43 @@ export class Enrico {
return this.keyring.publicKey;
}
- public encryptMessage(
+ public encryptMessagePre(
plaintext: Uint8Array | string,
- currentConditions?: ConditionSet
+ withConditions?: ConditionSet
): MessageKit {
- if (!currentConditions) {
- currentConditions = this.conditions;
+ if (!withConditions) {
+ withConditions = this.conditions;
}
+
+ if (!(this.encryptingKey instanceof PublicKey)) {
+ throw new Error('Wrong key type. Use encryptMessageCbd instead.');
+ }
+
return new MessageKit(
- this.policyEncryptingKey,
+ this.encryptingKey,
+ plaintext instanceof Uint8Array ? plaintext : toBytes(plaintext),
+ withConditions ? withConditions.toWASMConditions() : null
+ );
+ }
+
+ public encryptMessageCbd(
+ plaintext: Uint8Array | string,
+ withConditions?: ConditionSet
+ ): { ciphertext: Ciphertext; aad: Uint8Array } {
+ if (!withConditions) {
+ withConditions = this.conditions;
+ }
+
+ if (!(this.encryptingKey instanceof DkgPublicKey)) {
+ throw new Error('Wrong key type. Use encryptMessagePre instead.');
+ }
+
+ const aad = toBytes(withConditions?.toJson() ?? '');
+ const ciphertext = encrypt(
plaintext instanceof Uint8Array ? plaintext : toBytes(plaintext),
- currentConditions ? currentConditions.toWASMConditions() : null
+ aad,
+ this.encryptingKey
);
+ return { ciphertext, aad };
}
}
diff --git a/src/characters/porter.ts b/src/characters/porter.ts
index 4b67b99fd..47f403a8e 100644
--- a/src/characters/porter.ts
+++ b/src/characters/porter.ts
@@ -4,7 +4,7 @@ import {
RetrievalKit,
ThresholdDecryptionRequest,
ThresholdDecryptionResponse,
- TreasureMap
+ TreasureMap,
} from '@nucypher/nucypher-core';
import axios, { AxiosResponse } from 'axios';
import qs from 'qs';
@@ -66,13 +66,10 @@ export type RetrieveCFragsResponse = {
errors: Record;
};
-
-type PostDecryptRequest = Uint8Array;
+type PostDecryptRequest = Uint8Array;
type PostDecryptResult = Uint8Array;
-
-
export class Porter {
readonly porterUrl: URL;
@@ -144,12 +141,13 @@ export class Porter {
public async decrypt(
tDecRequest: ThresholdDecryptionRequest
- ): Promise {
+ ): Promise {
const data: PostDecryptRequest = tDecRequest.toBytes();
const resp: AxiosResponse = await axios.post(
new URL('/decrypt', this.porterUrl).toString(),
data
);
- return ThresholdDecryptionResponse.fromBytes(resp.data);
+ // TODO: In /cbd_decrypt, the response is a list of ThresholdDecryptionResponse
+ return [ThresholdDecryptionResponse.fromBytes(resp.data)];
}
}
diff --git a/src/characters/universal-bob.ts b/src/characters/pre-universal-bob.ts
similarity index 96%
rename from src/characters/universal-bob.ts
rename to src/characters/pre-universal-bob.ts
index 5f4182cd7..01b7d30ab 100644
--- a/src/characters/universal-bob.ts
+++ b/src/characters/pre-universal-bob.ts
@@ -16,7 +16,7 @@ import { base64ToU8Receiver, bytesEquals, toJson, zip } from '../utils';
import { Porter } from './porter';
-type decrypterJSON = {
+type PreTDecDecrypterJSON = {
porterUri: string;
policyEncryptingKeyBytes: Uint8Array;
encryptedTreasureMapBytes: Uint8Array;
@@ -24,7 +24,7 @@ type decrypterJSON = {
bobSecretKeyBytes: Uint8Array;
};
-export class tDecDecrypter {
+export class PreTDecDecrypter {
private readonly porter: Porter;
private readonly keyring: Keyring;
@@ -138,7 +138,7 @@ export class tDecDecrypter {
});
}
- public toObj(): decrypterJSON {
+ public toObj(): PreTDecDecrypterJSON {
return {
porterUri: this.porter.porterUrl.toString(),
policyEncryptingKeyBytes: this.policyEncryptingKey.toCompressedBytes(),
@@ -159,8 +159,8 @@ export class tDecDecrypter {
encryptedTreasureMapBytes,
publisherVerifyingKeyBytes,
bobSecretKeyBytes,
- }: decrypterJSON) {
- return new tDecDecrypter(
+ }: PreTDecDecrypterJSON) {
+ return new PreTDecDecrypter(
porterUri,
PublicKey.fromCompressedBytes(policyEncryptingKeyBytes),
EncryptedTreasureMap.fromBytes(encryptedTreasureMapBytes),
@@ -171,7 +171,7 @@ export class tDecDecrypter {
public static fromJSON(json: string) {
const config = JSON.parse(json, base64ToU8Receiver);
- return tDecDecrypter.fromObj(config);
+ return PreTDecDecrypter.fromObj(config);
}
public equals(other: tDecDecrypter): boolean {
diff --git a/src/dkg.ts b/src/dkg.ts
index 1230babd5..ece1d66ef 100644
--- a/src/dkg.ts
+++ b/src/dkg.ts
@@ -1,6 +1,8 @@
import { ethers } from 'ethers';
import {
AggregatedTranscript,
+ DkgPublicKey,
+ DkgPublicParameters,
EthereumAddress,
PublicKey as FerveoPublicKey,
Transcript,
@@ -11,20 +13,58 @@ import {
import { DkgCoordinatorAgent } from './agents/coordinator';
import { fromHexString } from './utils';
-export class DkgClient {
+// TOOD: Move to nucypher-core
+export enum FerveoVariant {
+ Simple = 0,
+ Precomputed = 1,
+}
+
+export interface DkgRitualJSON {
+ id: number;
+ dkgPublicKey: Uint8Array;
+ dkgPublicParams: Uint8Array;
+}
+
+export class DkgRitual {
constructor(
- private readonly provider: ethers.providers.Web3Provider,
- public readonly ritualId: number
+ public readonly id: number,
+ public readonly dkgPublicKey: DkgPublicKey,
+ public readonly dkgPublicParams: DkgPublicParameters
) {}
- public async verifyRitual(): Promise {
- const ritual = await DkgCoordinatorAgent.getRitual(
- this.provider,
- this.ritualId
+ public toObj(): DkgRitualJSON {
+ return {
+ id: this.id,
+ dkgPublicKey: this.dkgPublicKey.toBytes(),
+ dkgPublicParams: this.dkgPublicParams.toBytes(),
+ };
+ }
+
+ public static fromObj(json: DkgRitualJSON): DkgRitual {
+ return new DkgRitual(
+ json.id,
+ DkgPublicKey.fromBytes(json.dkgPublicKey),
+ DkgPublicParameters.fromBytes(json.dkgPublicParams)
);
+ }
+}
+
+export class DkgClient {
+ constructor(private readonly provider: ethers.providers.Web3Provider) {}
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async initializeRitual(
+ _provider: ethers.providers.Web3Provider,
+ _ritualParams: unknown
+ ): Promise {
+ // TODO: Create a new DKG ritual here
+ throw new Error('Not implemented');
+ }
+ public async verifyRitual(ritualId: number): Promise {
+ const ritual = await DkgCoordinatorAgent.getRitual(this.provider, ritualId);
const participants = await DkgCoordinatorAgent.getParticipants(
this.provider,
- this.ritualId
+ ritualId
);
const validatorMessages = participants.map((p) => {
diff --git a/src/index.ts b/src/index.ts
index 3087508d6..3ce372dbd 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -2,7 +2,7 @@
export { Alice } from './characters/alice';
export { Bob, RemoteBob } from './characters/bob';
export { Enrico } from './characters/enrico';
-export { tDecDecrypter } from './characters/universal-bob';
+export { PreTDecDecrypter } from './characters/pre-universal-bob';
export { Porter } from './characters/porter';
// Policies
@@ -30,7 +30,7 @@ export { conditions, CustomContextParam };
// SDK
export { Cohort } from './sdk/cohort';
-export { DeployedStrategy, Strategy } from './sdk/strategy';
+export { DeployedPreStrategy, PreStrategy } from './sdk/strategy/pre-strategy';
// Re-exports
export {
diff --git a/src/sdk/strategy/cbd-strategy.ts b/src/sdk/strategy/cbd-strategy.ts
new file mode 100644
index 000000000..6f60b5a9f
--- /dev/null
+++ b/src/sdk/strategy/cbd-strategy.ts
@@ -0,0 +1,160 @@
+import { SecretKey } from '@nucypher/nucypher-core';
+import { ethers } from 'ethers';
+
+import { CbdTDecDecrypter } from '../../characters/cbd-universal-bob';
+import { Enrico } from '../../characters/enrico';
+import { ConditionSet } from '../../conditions';
+import { DkgClient, DkgRitual, DkgRitualJSON } from '../../dkg';
+import { base64ToU8Receiver, u8ToBase64Replacer } from '../../utils';
+import { Cohort, CohortJSON } from '../cohort';
+
+type StrategyJSON = {
+ cohort: CohortJSON;
+ bobSecretKeyBytes: Uint8Array;
+ conditionSet?: ConditionSet;
+};
+
+type DeployedStrategyJSON = {
+ dkgRitual: DkgRitualJSON;
+ cohortConfig: CohortJSON;
+ bobSecretKeyBytes: Uint8Array;
+ conditionSet?: ConditionSet;
+};
+
+export class CbdStrategy {
+ private constructor(
+ public readonly cohort: Cohort,
+ private readonly bobSecretKey: SecretKey,
+ private readonly conditionSet?: ConditionSet
+ ) {}
+
+ public static create(
+ cohort: Cohort,
+ conditionSet?: ConditionSet,
+ bobSecretKey?: SecretKey
+ ) {
+ if (!bobSecretKey) {
+ bobSecretKey = SecretKey.random();
+ }
+ return new CbdStrategy(cohort, bobSecretKey, conditionSet);
+ }
+
+ public async deploy(
+ provider: ethers.providers.Web3Provider
+ ): Promise {
+ const dkgRitualParams = {
+ threshold: this.cohort.configuration.threshold,
+ shares: this.cohort.configuration.shares,
+ };
+ const dkgClient = new DkgClient(provider);
+ const dkgRitual = await dkgClient.initializeRitual(
+ provider,
+ dkgRitualParams
+ );
+
+ const encrypter = new Enrico(
+ dkgRitual.dkgPublicKey,
+ undefined,
+ this.conditionSet
+ );
+
+ const decrypter = new CbdTDecDecrypter(
+ this.cohort.configuration.porterUri,
+ dkgRitual.dkgPublicKey,
+ this.bobSecretKey
+ );
+
+ return new DeployedCbdStrategy(
+ this.cohort,
+ dkgRitual,
+ encrypter,
+ decrypter,
+ this.bobSecretKey,
+ this.conditionSet
+ );
+ }
+
+ public static fromJSON(json: string) {
+ const config = JSON.parse(json, base64ToU8Receiver);
+ return CbdStrategy.fromObj(config);
+ }
+
+ public toJSON() {
+ return JSON.stringify(this.toObj(), u8ToBase64Replacer);
+ }
+
+ private static fromObj({
+ cohort,
+ bobSecretKeyBytes,
+ conditionSet,
+ }: StrategyJSON) {
+ return new CbdStrategy(
+ Cohort.fromObj(cohort),
+ SecretKey.fromBEBytes(bobSecretKeyBytes),
+ conditionSet
+ );
+ }
+
+ public toObj(): StrategyJSON {
+ return {
+ cohort: this.cohort.toObj(),
+ bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
+ conditionSet: this.conditionSet,
+ };
+ }
+}
+
+export class DeployedCbdStrategy {
+ constructor(
+ public cohort: Cohort,
+ public dkgRitual: DkgRitual,
+ public encrypter: Enrico,
+ public decrypter: CbdTDecDecrypter,
+ private bobSecretKey: SecretKey,
+ public conditionSet?: ConditionSet
+ ) {}
+
+ public static fromJSON(json: string) {
+ const config = JSON.parse(json, base64ToU8Receiver);
+ return DeployedCbdStrategy.fromObj(config);
+ }
+
+ public toJSON() {
+ return JSON.stringify(this.toObj(), u8ToBase64Replacer);
+ }
+
+ private static fromObj({
+ dkgRitual,
+ cohortConfig,
+ bobSecretKeyBytes,
+ conditionSet,
+ }: DeployedStrategyJSON) {
+ const ritual = DkgRitual.fromObj(dkgRitual);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
+ const cohort = Cohort.fromObj(cohortConfig);
+ const encrypter = new Enrico(ritual.dkgPublicKey, undefined, conditionSet);
+
+ const decrypter = new CbdTDecDecrypter(
+ cohort.configuration.porterUri,
+ ritual.dkgPublicKey,
+ bobSecretKey
+ );
+ return new DeployedCbdStrategy(
+ cohort,
+ ritual,
+ encrypter,
+ decrypter,
+ bobSecretKey,
+ conditionSet
+ );
+ }
+
+ private toObj(): DeployedStrategyJSON {
+ return {
+ dkgRitual: this.dkgRitual.toObj(),
+ cohortConfig: this.cohort.toObj(),
+ bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
+ conditionSet: this.conditionSet,
+ };
+ }
+}
diff --git a/src/sdk/strategy.ts b/src/sdk/strategy/pre-strategy.ts
similarity index 88%
rename from src/sdk/strategy.ts
rename to src/sdk/strategy/pre-strategy.ts
index e8626bcd3..dd29a16b7 100644
--- a/src/sdk/strategy.ts
+++ b/src/sdk/strategy/pre-strategy.ts
@@ -6,15 +6,14 @@ import {
} from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
-import { Alice } from '../characters/alice';
-import { Bob } from '../characters/bob';
-import { Enrico } from '../characters/enrico';
-import { tDecDecrypter } from '../characters/universal-bob';
-import { ConditionSet, ConditionSetJSON } from '../conditions/condition-set';
-import { EnactedPolicy, EnactedPolicyJSON } from '../policies/policy';
-import { base64ToU8Receiver, bytesEquals, toJson } from '../utils';
-
-import { Cohort, CohortJSON } from './cohort';
+import { Alice } from '../../characters/alice';
+import { Bob } from '../../characters/bob';
+import { Enrico } from '../../characters/enrico';
+import { PreTDecDecrypter } from '../../characters/pre-universal-bob';
+import { ConditionSet, ConditionSetJSON } from '../../conditions';
+import { EnactedPolicy, EnactedPolicyJSON } from '../../policies/policy';
+import { base64ToU8Receiver, bytesEquals, toJson } from '../../utils';
+import { Cohort, CohortJSON } from '../cohort';
type StrategyJSON = {
cohort: CohortJSON;
@@ -32,7 +31,7 @@ type DeployedStrategyJSON = {
conditionSet?: ConditionSetJSON;
};
-export class Strategy {
+export class PreStrategy {
private constructor(
public readonly cohort: Cohort,
private readonly aliceSecretKey: SecretKey,
@@ -62,7 +61,7 @@ export class Strategy {
if (!endDate) {
endDate = new Date(Date.now() + 1000 * 60 * 60 * 24 * 30);
}
- return new Strategy(
+ return new PreStrategy(
cohort,
aliceSecretKey,
bobSecretKey,
@@ -75,7 +74,7 @@ export class Strategy {
public async deploy(
label: string,
provider: ethers.providers.Web3Provider
- ): Promise {
+ ): Promise {
const porterUri = this.cohort.configuration.porterUri;
const configuration = { porterUri };
const alice = Alice.fromSecretKey(
@@ -99,14 +98,14 @@ export class Strategy {
this.conditionSet
);
- const decrypter = new tDecDecrypter(
+ const decrypter = new PreTDecDecrypter(
this.cohort.configuration.porterUri,
policy.policyKey,
policy.encryptedTreasureMap,
alice.verifyingKey,
this.bobSecretKey
);
- return new DeployedStrategy(
+ return new DeployedPreStrategy(
label,
this.cohort,
policy,
@@ -121,7 +120,7 @@ export class Strategy {
const config = JSON.parse(json, base64ToU8Receiver);
config.startDate = new Date(config.startDate);
config.endDate = new Date(config.endDate);
- return Strategy.fromObj(config);
+ return PreStrategy.fromObj(config);
}
public toJSON() {
@@ -136,7 +135,7 @@ export class Strategy {
startDate,
endDate,
}: StrategyJSON) {
- return new Strategy(
+ return new PreStrategy(
Cohort.fromObj(cohort),
SecretKey.fromBEBytes(aliceSecretKeyBytes),
SecretKey.fromBEBytes(bobSecretKeyBytes),
@@ -177,20 +176,20 @@ export class Strategy {
}
}
-export class DeployedStrategy {
+export class DeployedPreStrategy {
constructor(
public label: string,
public cohort: Cohort,
public policy: EnactedPolicy,
public encrypter: Enrico,
- public decrypter: tDecDecrypter,
+ public decrypter: PreTDecDecrypter,
private bobSecretKey: SecretKey,
public conditionSet?: ConditionSet
) {}
public static fromJSON(json: string) {
const config = JSON.parse(json, base64ToU8Receiver);
- return DeployedStrategy.fromObj(config);
+ return DeployedPreStrategy.fromObj(config);
}
public toJSON() {
@@ -235,14 +234,14 @@ export class DeployedStrategy {
conditionSetOrUndefined
);
- const decrypter = new tDecDecrypter(
+ const decrypter = new PreTDecDecrypter(
cohort.configuration.porterUri,
policyKey,
encryptedTreasureMap,
aliceVerifyingKey,
bobSecretKey
);
- return new DeployedStrategy(
+ return new DeployedPreStrategy(
label,
cohort,
newPolicy,
diff --git a/test/acceptance/alice-grants.test.ts b/test/acceptance/alice-grants.test.ts
index c234c1078..741877a04 100644
--- a/test/acceptance/alice-grants.test.ts
+++ b/test/acceptance/alice-grants.test.ts
@@ -88,7 +88,7 @@ describe('story: alice shares message with bob through policy', () => {
it('enrico encrypts the message', () => {
const enrico = new Enrico(policyEncryptingKey);
- encryptedMessage = enrico.encryptMessage(toBytes(message));
+ encryptedMessage = enrico.encryptMessagePre(toBytes(message));
});
it('bob retrieves and decrypts the message', async () => {
diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts
index 934bb2985..86be24fe6 100644
--- a/test/docs/cbd.test.ts
+++ b/test/docs/cbd.test.ts
@@ -1,7 +1,7 @@
import { MessageKit, VerifiedKeyFrag } from '@nucypher/nucypher-core';
import { providers } from 'ethers';
-import { Cohort, conditions, SecretKey, Strategy } from '../../src';
+import { Cohort, conditions, PreStrategy, SecretKey } from '../../src';
import { Ursula } from '../../src/characters/porter';
import { toBytes } from '../../src/utils';
import {
@@ -80,7 +80,7 @@ describe('Get Started (CBD PoC)', () => {
]);
// 4. Build a Strategy
- const newStrategy = Strategy.create(newCohort, conditions);
+ const newStrategy = PreStrategy.create(newCohort, conditions);
const MMprovider = await detectEthereumProvider();
const mumbai = providers.getNetwork(80001);
@@ -105,7 +105,7 @@ describe('Get Started (CBD PoC)', () => {
const encrypter = newDeployed.encrypter;
const plaintext = 'this is a secret';
- const encryptedMessageKit = encrypter.encryptMessage(
+ const encryptedMessageKit = encrypter.encryptMessagePre(
plaintext,
new ConditionSet([NFTBalance])
);
diff --git a/test/integration/dkg-client.test.ts b/test/integration/dkg-client.test.ts
index c1d002086..824c30ab9 100644
--- a/test/integration/dkg-client.test.ts
+++ b/test/integration/dkg-client.test.ts
@@ -2,13 +2,16 @@ import { SecretKey } from '@nucypher/nucypher-core';
import { DkgCoordinatorAgent } from '../../src/agents/coordinator';
import { DkgClient } from '../../src/dkg';
-import { fakeDkgParticipants, fakeDkgRitual, fakeWeb3Provider } from '../utils';
-
-const ritualId = 0;
+import {
+ fakeCoordinatorRitual,
+ fakeDkgParticipants,
+ fakeWeb3Provider,
+} from '../utils';
+const ritualId = 1;
jest.mock('../../src/agents/coordinator', () => ({
DkgCoordinatorAgent: {
- getRitual: () => Promise.resolve(fakeDkgRitual(ritualId)),
+ getRitual: () => Promise.resolve(fakeCoordinatorRitual(ritualId)),
getParticipants: () => Promise.resolve(fakeDkgParticipants()),
},
}));
@@ -40,8 +43,8 @@ describe('DkgClient', () => {
it('verifies the dkg ritual', async () => {
const provider = fakeWeb3Provider(SecretKey.random().toBEBytes());
- const dkgClient = new DkgClient(provider, ritualId);
- const isValid = await dkgClient.verifyRitual();
+ const dkgClient = new DkgClient(provider);
+ const isValid = await dkgClient.verifyRitual(ritualId);
expect(isValid).toBeTruthy();
});
});
diff --git a/test/integration/enrico.test.ts b/test/integration/enrico.test.ts
index 66318607b..bd90e5d5a 100644
--- a/test/integration/enrico.test.ts
+++ b/test/integration/enrico.test.ts
@@ -24,7 +24,7 @@ describe('enrico', () => {
const policyKey = alice.getPolicyEncryptingKeyFromLabel(label);
const enrico = new Enrico(policyKey);
- const encrypted = enrico.encryptMessage(toBytes(message));
+ const encrypted = enrico.encryptMessagePre(toBytes(message));
const aliceKeyring = (alice as any).keyring;
const aliceSk = await aliceKeyring.getSecretKeyFromLabel(label);
@@ -42,7 +42,7 @@ describe('enrico', () => {
const plaintext = 'Plaintext message';
const plaintextBytes = toBytes(plaintext);
- const encrypted = enrico.encryptMessage(plaintextBytes);
+ const encrypted = enrico.encryptMessagePre(plaintextBytes);
// Alice can decrypt capsule she created
const aliceSk = await (alice as any).keyring.getSecretKeyFromLabel(label);
@@ -108,7 +108,7 @@ describe('enrico', () => {
const conditions = new ConditionSet([ownsBufficornNFT]);
const enrico = new Enrico(policyKey, undefined, conditions);
- const encrypted = enrico.encryptMessage(toBytes(message));
+ const encrypted = enrico.encryptMessagePre(toBytes(message));
const aliceKeyring = (alice as any).keyring;
const aliceSk = await aliceKeyring.getSecretKeyFromLabel(label);
@@ -139,7 +139,7 @@ describe('enrico', () => {
const updatedConditions = new ConditionSet([ownsNonsenseNFT]);
const enrico = new Enrico(policyKey, undefined, conditions);
- const encrypted = enrico.encryptMessage(
+ const encrypted = enrico.encryptMessagePre(
toBytes(message),
updatedConditions
);
diff --git a/test/integration/pre.test.ts b/test/integration/pre.test.ts
index 2501509cb..1a9fb5600 100644
--- a/test/integration/pre.test.ts
+++ b/test/integration/pre.test.ts
@@ -54,7 +54,7 @@ describe('proxy reencryption', () => {
const policyEncryptingKey = alice.getPolicyEncryptingKeyFromLabel(label);
const enrico = new Enrico(policyEncryptingKey);
- const encryptedMessage = enrico.encryptMessage(plaintext);
+ const encryptedMessage = enrico.encryptMessagePre(plaintext);
const ursulaAddresses = ursulas.map((ursula) => ursula.checksumAddress);
const reencrypted = verifiedKFrags.map((kFrag) =>
@@ -101,7 +101,7 @@ describe('proxy reencryption', () => {
]);
const enrico = new Enrico(policyEncryptingKey, undefined, conditionsSet);
- const encryptedMessage = enrico.encryptMessage(plaintext);
+ const encryptedMessage = enrico.encryptMessagePre(plaintext);
const ursulaAddresses = ursulas.map((ursula) => ursula.checksumAddress);
const reencrypted = verifiedKFrags.map((kFrag) =>
diff --git a/test/unit/cbd-strategy.test.ts b/test/unit/cbd-strategy.test.ts
new file mode 100644
index 000000000..c32fa3cca
--- /dev/null
+++ b/test/unit/cbd-strategy.test.ts
@@ -0,0 +1,209 @@
+import { SecretKey } from '@nucypher/nucypher-core';
+
+import { Cohort, conditions } from '../../src';
+import { FerveoVariant } from '../../src/dkg';
+import { CbdStrategy } from '../../src/sdk/strategy/cbd-strategy';
+import { toBytes } from '../../src/utils';
+import {
+ fakeDkgRitual,
+ fakeDkgRitualE2e,
+ fakeUrsulas,
+ fakeWeb3Provider,
+ mockDecrypt,
+ mockGetUrsulas,
+ mockInitializeRitual,
+} from '../utils';
+
+import {
+ aliceSecretKeyBytes,
+ bobSecretKeyBytes,
+ strategyJSON,
+} from './testVariables';
+
+const {
+ predefined: { ERC721Ownership },
+ ConditionSet,
+} = conditions;
+
+describe('CbdStrategy', () => {
+ const cohortConfig = {
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ };
+ const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
+ const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
+ Date.now = jest.fn(() => 1487076708000);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ it('can create CbdStrategy from configuration', async () => {
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
+ const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
+
+ const testCohort = await Cohort.create(cohortConfig);
+ const testStrategy = CbdStrategy.create(
+ testCohort,
+ undefined,
+ bobSecretKey
+ );
+
+ const expectedUrsulas = mockedUrsulas.map(
+ (ursula) => ursula.checksumAddress
+ );
+ expect(getUrsulasSpy).toHaveBeenCalled();
+ expect(testStrategy.cohort.ursulaAddresses).toEqual(expectedUrsulas);
+ });
+
+ // TODO: Update this test
+ it('can export to JSON', async () => {
+ // const mockedUrsulas = fakeUrsulas().slice(0, 3);
+ // const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
+ // const testCohort = await Cohort.create(cohortConfig);
+ // const testStrategy = CbdStrategy.create(
+ // testCohort,
+ // undefined,
+ // bobSecretKey
+ // );
+ //
+ // const configJSON = testStrategy.toJSON();
+ // expect(configJSON).toEqual(strategyJSON);
+ // expect(getUrsulasSpy).toHaveBeenCalled();
+ });
+
+ it('can import from JSON', async () => {
+ const testStrategy = CbdStrategy.fromJSON(strategyJSON);
+ const expectedUrsulas = [
+ '0x5cf1703a1c99a4b42eb056535840e93118177232',
+ '0x7fff551249d223f723557a96a0e1a469c79cc934',
+ '0x9c7c824239d3159327024459ad69bb215859bd25',
+ ];
+ expect(testStrategy.cohort.ursulaAddresses).toEqual(expectedUrsulas);
+ });
+
+ it('can deploy and return DeployedStrategy', async () => {
+ const fakeRitual = fakeDkgRitual(FerveoVariant.Precomputed);
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
+ const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
+ const initRitualSpy = mockInitializeRitual(fakeRitual);
+
+ const testCohort = await Cohort.create(cohortConfig);
+ const testStrategy = CbdStrategy.create(
+ testCohort,
+ undefined,
+ aliceSecretKey
+ );
+ const testDeployed = await testStrategy.deploy(aliceProvider);
+ expect(testDeployed.dkgRitual.id).toEqual(fakeRitual.id);
+ expect(getUrsulasSpy).toHaveBeenCalled();
+ expect(initRitualSpy).toHaveBeenCalled();
+ });
+});
+
+describe('CbdDeployedStrategy', () => {
+ const cohortConfig = {
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ };
+ const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+
+ // TODO: Update this test
+ // it('can export to JSON', async () => {
+ // const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
+ // const mockedUrsulas = fakeUrsulas().slice(0, 3);
+ // const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
+ //
+ // const testCohort = await Cohort.create(cohortConfig);
+ // const testStrategy = CbdStrategy.create(
+ // testCohort,
+ // undefined,
+ // bobSecretKey
+ // );
+ // const testDeployed = await testStrategy.deploy(aliceProvider);
+ // expect(getUrsulasSpy).toHaveBeenCalled();
+ //
+ // const configJSON = testDeployed.toJSON();
+ // expect(configJSON).toEqual(deployedStrategyJSON);
+ // });
+
+ // TODO: Update this test
+ // it('can import from JSON', async () => {
+ // const importedStrategy = DeployedCbdStrategy.fromJSON(deployedStrategyJSON);
+ // const configJSON = importedStrategy.toJSON();
+ // expect(configJSON).toEqual(deployedStrategyJSON);
+ // });
+
+ it('can encrypt and decrypt', async () => {
+ const variant = FerveoVariant.Precomputed;
+ const fakeRitual = fakeDkgRitual(variant);
+ const { decryptionShares } = fakeDkgRitualE2e(variant);
+ const web3Provider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
+ const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
+ const initializeRitualSpy = mockInitializeRitual(fakeRitual);
+
+ const cohort = await Cohort.create(cohortConfig);
+ const strategy = CbdStrategy.create(cohort, undefined, bobSecretKey);
+
+ const deployedStrategy = await strategy.deploy(web3Provider);
+ expect(getUrsulasSpy).toHaveBeenCalled();
+ expect(initializeRitualSpy).toHaveBeenCalled();
+
+ const encrypter = deployedStrategy.encrypter;
+ const decrypter = deployedStrategy.decrypter;
+
+ const ownsNFT = new ERC721Ownership({
+ contractAddress: '0x1e988ba4692e52Bc50b375bcC8585b95c48AaD77',
+ parameters: [3591],
+ chain: 5,
+ });
+ const conditionSet = new ConditionSet([ownsNFT]);
+
+ const plaintext = 'this is a secret';
+ const { ciphertext, aad } = encrypter.encryptMessageCbd(
+ plaintext,
+ conditionSet
+ );
+
+ // Setup mocks for `retrieveAndDecrypt`
+ const getUrsulasSpy2 = mockGetUrsulas(mockedUrsulas);
+ const decryptSpy = mockDecrypt(decryptionShares);
+
+ const decryptedMessage = await decrypter.retrieveAndDecrypt(
+ web3Provider,
+ conditionSet,
+ deployedStrategy.dkgRitual,
+ variant,
+ ciphertext,
+ aad
+ );
+ expect(getUrsulasSpy2).toHaveBeenCalled();
+ expect(decryptSpy).toHaveBeenCalled();
+ expect(decryptedMessage[0]).toEqual(toBytes(plaintext));
+ });
+});
+
+// TODO: Update this test
+describe('cbd tdec decrypter', () => {
+ // const importedStrategy = DeployedCbdStrategy.fromJSON(deployedStrategyJSON);
+ //
+ // it('can export to JSON', () => {
+ // const configJSON = importedStrategy.decrypter.toJSON();
+ // expect(configJSON).toEqual(decrypterJSON);
+ // });
+ //
+ // it('can import from JSON', () => {
+ // const decrypter = PreTDecDecrypter.fromJSON(decrypterJSON);
+ // const configJSON = decrypter.toJSON();
+ // expect(configJSON).toEqual(decrypterJSON);
+ // });
+});
diff --git a/test/unit/strategy.test.ts b/test/unit/pre-strategy.test.ts
similarity index 83%
rename from test/unit/strategy.test.ts
rename to test/unit/pre-strategy.test.ts
index 18b6bd0e0..b28d68b55 100644
--- a/test/unit/strategy.test.ts
+++ b/test/unit/pre-strategy.test.ts
@@ -6,9 +6,9 @@ import {
import {
conditions,
- DeployedStrategy,
- Strategy,
- tDecDecrypter,
+ DeployedPreStrategy,
+ PreStrategy,
+ PreTDecDecrypter,
} from '../../src';
import { Ursula } from '../../src/characters/porter';
import { fromBase64, toBytes } from '../../src/utils';
@@ -49,14 +49,25 @@ const ownsNFT = new ERC721Ownership({
const conditionSet = new ConditionSet([ownsNFT]);
const mockedUrsulas = fakeUrsulas().slice(0, 3);
+describe('PreStrategy', () => {
+ const cohortConfig = {
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ };
+ const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
+ const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
+ const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
+ Date.now = jest.fn(() => 1487076708000);
+
describe('Strategy', () => {
afterEach(() => {
jest.restoreAllMocks();
});
- it('creates a Strategy', async () => {
+ it('creates a PreStrategy', async () => {
const cohort = await makeCohort(mockedUrsulas);
- const strategy = Strategy.create(
+ const strategy = PreStrategy.create(
cohort,
conditionSet,
aliceSecretKey,
@@ -67,20 +78,20 @@ describe('Strategy', () => {
it('serializes to plain object', async () => {
const cohort = await makeCohort(mockedUrsulas);
- const strategy = Strategy.create(
+ const strategy = PreStrategy.create(
cohort,
conditionSet,
aliceSecretKey,
bobSecretKey
);
const asObject = strategy.toObj();
- const fromObject = Strategy.fromObj(asObject);
+ const fromObject = PreStrategy.fromObj(asObject);
expect(fromObject.equals(strategy)).toBeTruthy();
});
it('serializes to JSON', async () => {
const cohort = await makeCohort(mockedUrsulas);
- const strategy = Strategy.create(
+ const strategy = PreStrategy.create(
cohort,
conditionSet,
aliceSecretKey,
@@ -88,7 +99,7 @@ describe('Strategy', () => {
);
const asJson = strategy.toJSON();
- const fromJSON = Strategy.fromJSON(asJson);
+ const fromJSON = PreStrategy.fromJSON(asJson);
expect(fromJSON.equals(strategy)).toBeTruthy();
});
@@ -100,7 +111,10 @@ describe('Strategy', () => {
const encryptTreasureMapSpy = mockEncryptTreasureMap();
const cohort = await makeCohort(mockedUrsulas);
- const strategy = Strategy.create(cohort, conditionSet, aliceSecretKey);
+ const strategy = PreStrategy.create(
+ cohort, conditionSet,
+ aliceSecretKey
+ );
const label = 'test';
const deployedStrategy = await strategy.deploy(label, aliceProvider);
@@ -115,7 +129,7 @@ describe('Strategy', () => {
});
});
-describe('Deployed Strategy', () => {
+describe('PreDeployedStrategy', () => {
afterEach(() => {
jest.restoreAllMocks();
});
@@ -131,7 +145,7 @@ describe('Deployed Strategy', () => {
);
const cohort = await makeCohort(mockedUrsulas);
- const strategy = Strategy.create(
+ const strategy = PreStrategy.create(
cohort,
conditionSet,
aliceSecretKey,
@@ -149,7 +163,7 @@ describe('Deployed Strategy', () => {
expect(encryptTreasureMapSpy).toHaveBeenCalled();
const asJson = deployedStrategy.toJSON();
- const fromJson = DeployedStrategy.fromJSON(asJson);
+ const fromJson = DeployedPreStrategy.fromJSON(asJson);
expect(fromJson.equals(deployedStrategy)).toBeTruthy();
});
@@ -164,7 +178,7 @@ describe('Deployed Strategy', () => {
const encryptTreasureMapSpy = mockEncryptTreasureMap();
const cohort = await makeCohort(mockedUrsulas);
- const strategy = Strategy.create(
+ const strategy = PreStrategy.create(
cohort,
conditionSet,
aliceSecretKey,
@@ -183,7 +197,7 @@ describe('Deployed Strategy', () => {
const plaintext = 'this is a secret';
encrypter.conditions = conditionSet;
- const encryptedMessageKit = encrypter.encryptMessage(plaintext);
+ const encryptedMessageKit = encrypter.encryptMessagePre(plaintext);
// Setup mocks for `retrieveAndDecrypt`
const getUrsulasSpy2 = mockGetUrsulas(mockedUrsulas);
@@ -212,12 +226,12 @@ describe('Deployed Strategy', () => {
});
});
-describe('tDecDecrypter', () => {
- const decrypter = DeployedStrategy.fromJSON(deployedStrategyJSON).decrypter;
+describe('pre tdec decrypter', () => {
+ const decrypter = DeployedPreStrategy.fromJSON(deployedStrategyJSON).decrypter;
it('serializes to JSON', () => {
const asJson = decrypter.toJSON();
- const fromJson = tDecDecrypter.fromJSON(asJson);
+ const fromJson = PreTDecDecrypter.fromJSON(asJson);
expect(fromJson.equals(decrypter)).toBeTruthy();
});
});
diff --git a/test/utils.ts b/test/utils.ts
index a0299b502..5d8bfad79 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -9,6 +9,7 @@ import {
PublicKey,
reencrypt,
SecretKey,
+ ThresholdDecryptionResponse,
VerifiedCapsuleFrag,
VerifiedKeyFrag,
} from '@nucypher/nucypher-core';
@@ -32,13 +33,14 @@ import {
} from 'ferveo-wasm';
import { Alice, Bob, Cohort, Configuration, RemoteBob } from '../src';
-import { DkgParticipant, DkgRitual } from '../src/agents/coordinator';
+import { CoordinatorRitual, DkgParticipant } from '../src/agents/coordinator';
import {
GetUrsulasResponse,
Porter,
RetrieveCFragsResponse,
Ursula,
} from '../src/characters/porter';
+import { DkgClient, DkgRitual, FerveoVariant } from '../src/dkg';
import { BlockchainPolicy, PreEnactedPolicy } from '../src/policies/policy';
import { ChecksumAddress } from '../src/types';
import { toBytes, toHexString, zip } from '../src/utils';
@@ -229,8 +231,11 @@ export const mockDetectEthereumProvider = () => {
});
};
-const fakeDkgRitualE2e = (variant: 'precomputed' | 'simple') => {
- if (variant !== 'precomputed' && variant !== 'simple') {
+export const fakeDkgRitualE2e = (variant: FerveoVariant) => {
+ if (
+ variant !== FerveoVariant.Simple &&
+ variant !== FerveoVariant.Precomputed
+ ) {
throw new Error(`Invalid variant: ${variant}`);
}
@@ -299,7 +304,7 @@ const fakeDkgRitualE2e = (variant: 'precomputed' | 'simple') => {
let decryptionShare;
- if (variant === 'precomputed') {
+ if (variant === FerveoVariant.Precomputed) {
decryptionShare = aggregate.createDecryptionSharePrecomputed(
dkg,
ciphertext,
@@ -321,7 +326,7 @@ const fakeDkgRitualE2e = (variant: 'precomputed' | 'simple') => {
// This part is in the client API
let sharedSecret;
- if (variant === 'precomputed') {
+ if (variant === FerveoVariant.Precomputed) {
sharedSecret = combineDecryptionSharesPrecomputed(decryptionShares);
} else {
sharedSecret = combineDecryptionSharesSimple(
@@ -354,11 +359,12 @@ const fakeDkgRitualE2e = (variant: 'precomputed' | 'simple') => {
aad,
ciphertext,
serverAggregate,
+ decryptionShares,
};
};
-export const fakeDkgRitual = (ritualId: number): DkgRitual => {
- const ritual = fakeDkgRitualE2e('precomputed');
+export const fakeCoordinatorRitual = (ritualId: number): CoordinatorRitual => {
+ const ritual = fakeDkgRitualE2e(FerveoVariant.Precomputed);
return {
id: ritualId,
initiator: ritual.validators[0].address.toString(),
@@ -375,7 +381,7 @@ export const fakeDkgRitual = (ritualId: number): DkgRitual => {
};
export const fakeDkgParticipants = (): DkgParticipant[] => {
- const ritual = fakeDkgRitualE2e('precomputed');
+ const ritual = fakeDkgRitualE2e(FerveoVariant.Precomputed);
return zip(
zip(ritual.validators, ritual.transcripts),
ritual.validator_keypairs
@@ -389,6 +395,30 @@ export const fakeDkgParticipants = (): DkgParticipant[] => {
});
};
+export const mockDecrypt = (
+ decryptionShares: (DecryptionSharePrecomputed | DecryptionShareSimple)[]
+) => {
+ const result = decryptionShares.map(
+ (share) => new ThresholdDecryptionResponse(share.toBytes())
+ );
+ return jest.spyOn(Porter.prototype, 'decrypt').mockImplementation(() => {
+ return Promise.resolve(result);
+ });
+};
+
+export const fakeDkgRitual = (variant: FerveoVariant) => {
+ const ritual = fakeDkgRitualE2e(variant);
+ return new DkgRitual(1, ritual.dkg.finalKey(), ritual.dkg.publicParams());
+};
+
+export const mockInitializeRitual = (fakeRitual: unknown) => {
+ return jest
+ .spyOn(DkgClient.prototype as any, 'initializeRitual')
+ .mockImplementation(() => {
+ return Promise.resolve(fakeRitual);
+ });
+};
+
export const makeCohort = async (ursulas: Ursula[]) => {
const getUrsulasSpy = mockGetUrsulas(ursulas);
const config = {
From b24af3ff2dc10b89d9f9128c01fa6ed7ebe7692a Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Fri, 19 May 2023 12:48:44 +0200
Subject: [PATCH 42/98] fix e2e test
---
src/characters/cbd-universal-bob.ts | 37 +------
src/sdk/strategy/cbd-strategy.ts | 42 ++------
test/unit/cbd-strategy.test.ts | 159 +++++++++++++++-------------
test/unit/pre-strategy.test.ts | 17 +--
test/unit/testVariables.ts | 45 +++++++-
test/utils.ts | 99 ++++++++++++-----
6 files changed, 214 insertions(+), 185 deletions(-)
diff --git a/src/characters/cbd-universal-bob.ts b/src/characters/cbd-universal-bob.ts
index 2a1f96fc9..01c50e4bd 100644
--- a/src/characters/cbd-universal-bob.ts
+++ b/src/characters/cbd-universal-bob.ts
@@ -1,11 +1,4 @@
-import {
- Context,
- MessageKit,
- PublicKey,
- SecretKey,
- Signer,
- ThresholdDecryptionRequest,
-} from '@nucypher/nucypher-core';
+import { Context, ThresholdDecryptionRequest } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
import {
combineDecryptionSharesPrecomputed,
@@ -20,8 +13,6 @@ import { Ciphertext } from 'ferveo-wasm';
import { ConditionSet } from '../conditions';
import { DkgRitual, FerveoVariant } from '../dkg';
-import { Keyring } from '../keyring';
-import { PolicyMessageKit } from '../kits/message';
import { base64ToU8Receiver, u8ToBase64Replacer } from '../utils';
import { Porter } from './porter';
@@ -29,34 +20,15 @@ import { Porter } from './porter';
type CbdTDecDecrypterJSON = {
porterUri: string;
encryptingKeyBytes: Uint8Array;
- bobSecretKeyBytes: Uint8Array;
};
export class CbdTDecDecrypter {
private readonly porter: Porter;
- private readonly keyring: Keyring;
// private readonly verifyingKey: Keyring;
- constructor(
- porterUri: string,
- private readonly dkgPublicKey: DkgPublicKey,
- secretKey: SecretKey
- ) {
+ constructor(porterUri: string, private readonly dkgPublicKey: DkgPublicKey) {
this.porter = new Porter(porterUri);
- this.keyring = new Keyring(secretKey);
- }
-
- public get decryptingKey(): PublicKey {
- return this.keyring.publicKey;
- }
-
- public get signer(): Signer {
- return this.keyring.signer;
- }
-
- public decrypt(messageKit: MessageKit | PolicyMessageKit): Uint8Array {
- return this.keyring.decrypt(messageKit);
}
public async retrieveAndDecrypt(
@@ -138,7 +110,6 @@ export class CbdTDecDecrypter {
return {
porterUri: this.porter.porterUrl.toString(),
encryptingKeyBytes: this.dkgPublicKey.toBytes(),
- bobSecretKeyBytes: this.keyring.secretKey.toBEBytes(),
};
}
@@ -149,12 +120,10 @@ export class CbdTDecDecrypter {
private static fromObj({
porterUri,
encryptingKeyBytes,
- bobSecretKeyBytes,
}: CbdTDecDecrypterJSON) {
return new CbdTDecDecrypter(
porterUri,
- DkgPublicKey.fromBytes(encryptingKeyBytes),
- SecretKey.fromBEBytes(bobSecretKeyBytes)
+ DkgPublicKey.fromBytes(encryptingKeyBytes)
);
}
diff --git a/src/sdk/strategy/cbd-strategy.ts b/src/sdk/strategy/cbd-strategy.ts
index 6f60b5a9f..6219afbe7 100644
--- a/src/sdk/strategy/cbd-strategy.ts
+++ b/src/sdk/strategy/cbd-strategy.ts
@@ -1,4 +1,3 @@
-import { SecretKey } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
import { CbdTDecDecrypter } from '../../characters/cbd-universal-bob';
@@ -10,33 +9,23 @@ import { Cohort, CohortJSON } from '../cohort';
type StrategyJSON = {
cohort: CohortJSON;
- bobSecretKeyBytes: Uint8Array;
conditionSet?: ConditionSet;
};
type DeployedStrategyJSON = {
dkgRitual: DkgRitualJSON;
cohortConfig: CohortJSON;
- bobSecretKeyBytes: Uint8Array;
conditionSet?: ConditionSet;
};
export class CbdStrategy {
private constructor(
public readonly cohort: Cohort,
- private readonly bobSecretKey: SecretKey,
private readonly conditionSet?: ConditionSet
) {}
- public static create(
- cohort: Cohort,
- conditionSet?: ConditionSet,
- bobSecretKey?: SecretKey
- ) {
- if (!bobSecretKey) {
- bobSecretKey = SecretKey.random();
- }
- return new CbdStrategy(cohort, bobSecretKey, conditionSet);
+ public static create(cohort: Cohort, conditionSet?: ConditionSet) {
+ return new CbdStrategy(cohort, conditionSet);
}
public async deploy(
@@ -60,8 +49,7 @@ export class CbdStrategy {
const decrypter = new CbdTDecDecrypter(
this.cohort.configuration.porterUri,
- dkgRitual.dkgPublicKey,
- this.bobSecretKey
+ dkgRitual.dkgPublicKey
);
return new DeployedCbdStrategy(
@@ -69,7 +57,6 @@ export class CbdStrategy {
dkgRitual,
encrypter,
decrypter,
- this.bobSecretKey,
this.conditionSet
);
}
@@ -83,22 +70,13 @@ export class CbdStrategy {
return JSON.stringify(this.toObj(), u8ToBase64Replacer);
}
- private static fromObj({
- cohort,
- bobSecretKeyBytes,
- conditionSet,
- }: StrategyJSON) {
- return new CbdStrategy(
- Cohort.fromObj(cohort),
- SecretKey.fromBEBytes(bobSecretKeyBytes),
- conditionSet
- );
+ private static fromObj({ cohort, conditionSet }: StrategyJSON) {
+ return new CbdStrategy(Cohort.fromObj(cohort), conditionSet);
}
public toObj(): StrategyJSON {
return {
cohort: this.cohort.toObj(),
- bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
conditionSet: this.conditionSet,
};
}
@@ -110,7 +88,6 @@ export class DeployedCbdStrategy {
public dkgRitual: DkgRitual,
public encrypter: Enrico,
public decrypter: CbdTDecDecrypter,
- private bobSecretKey: SecretKey,
public conditionSet?: ConditionSet
) {}
@@ -126,34 +103,29 @@ export class DeployedCbdStrategy {
private static fromObj({
dkgRitual,
cohortConfig,
- bobSecretKeyBytes,
conditionSet,
}: DeployedStrategyJSON) {
const ritual = DkgRitual.fromObj(dkgRitual);
- const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
const cohort = Cohort.fromObj(cohortConfig);
const encrypter = new Enrico(ritual.dkgPublicKey, undefined, conditionSet);
const decrypter = new CbdTDecDecrypter(
cohort.configuration.porterUri,
- ritual.dkgPublicKey,
- bobSecretKey
+ ritual.dkgPublicKey
);
return new DeployedCbdStrategy(
cohort,
ritual,
encrypter,
decrypter,
- bobSecretKey,
conditionSet
);
}
- private toObj(): DeployedStrategyJSON {
+ public toObj(): DeployedStrategyJSON {
return {
dkgRitual: this.dkgRitual.toObj(),
cohortConfig: this.cohort.toObj(),
- bobSecretKeyBytes: this.bobSecretKey.toBEBytes(),
conditionSet: this.conditionSet,
};
}
diff --git a/test/unit/cbd-strategy.test.ts b/test/unit/cbd-strategy.test.ts
index c32fa3cca..8959f0006 100644
--- a/test/unit/cbd-strategy.test.ts
+++ b/test/unit/cbd-strategy.test.ts
@@ -1,12 +1,18 @@
import { SecretKey } from '@nucypher/nucypher-core';
import { Cohort, conditions } from '../../src';
+import { CbdTDecDecrypter } from '../../src/characters/cbd-universal-bob';
import { FerveoVariant } from '../../src/dkg';
-import { CbdStrategy } from '../../src/sdk/strategy/cbd-strategy';
+import {
+ CbdStrategy,
+ DeployedCbdStrategy,
+} from '../../src/sdk/strategy/cbd-strategy';
import { toBytes } from '../../src/utils';
import {
+ fakeDkgFlow,
fakeDkgRitual,
- fakeDkgRitualE2e,
+ fakeDkgTDecFlowE2e,
+ fakeTDecFlow,
fakeUrsulas,
fakeWeb3Provider,
mockDecrypt,
@@ -16,8 +22,10 @@ import {
import {
aliceSecretKeyBytes,
- bobSecretKeyBytes,
- strategyJSON,
+ cbdDecrypterJSON,
+ cbdStrategyJSON,
+ deployedCbdStrategyObj,
+ preStrategyJSON,
} from './testVariables';
const {
@@ -32,7 +40,6 @@ describe('CbdStrategy', () => {
porterUri: 'https://_this.should.crash',
};
const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
- const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
Date.now = jest.fn(() => 1487076708000);
@@ -45,11 +52,7 @@ describe('CbdStrategy', () => {
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const testCohort = await Cohort.create(cohortConfig);
- const testStrategy = CbdStrategy.create(
- testCohort,
- undefined,
- bobSecretKey
- );
+ const testStrategy = CbdStrategy.create(testCohort, undefined);
const expectedUrsulas = mockedUrsulas.map(
(ursula) => ursula.checksumAddress
@@ -60,22 +63,18 @@ describe('CbdStrategy', () => {
// TODO: Update this test
it('can export to JSON', async () => {
- // const mockedUrsulas = fakeUrsulas().slice(0, 3);
- // const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
- // const testCohort = await Cohort.create(cohortConfig);
- // const testStrategy = CbdStrategy.create(
- // testCohort,
- // undefined,
- // bobSecretKey
- // );
- //
- // const configJSON = testStrategy.toJSON();
- // expect(configJSON).toEqual(strategyJSON);
- // expect(getUrsulasSpy).toHaveBeenCalled();
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
+ const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
+ const testCohort = await Cohort.create(cohortConfig);
+ const testStrategy = CbdStrategy.create(testCohort, undefined);
+
+ const configJSON = testStrategy.toJSON();
+ expect(configJSON).toEqual(cbdStrategyJSON);
+ expect(getUrsulasSpy).toHaveBeenCalled();
});
it('can import from JSON', async () => {
- const testStrategy = CbdStrategy.fromJSON(strategyJSON);
+ const testStrategy = CbdStrategy.fromJSON(preStrategyJSON);
const expectedUrsulas = [
'0x5cf1703a1c99a4b42eb056535840e93118177232',
'0x7fff551249d223f723557a96a0e1a469c79cc934',
@@ -85,17 +84,15 @@ describe('CbdStrategy', () => {
});
it('can deploy and return DeployedStrategy', async () => {
- const fakeRitual = fakeDkgRitual(FerveoVariant.Precomputed);
+ const variant = FerveoVariant.Precomputed;
+ const fakeE2ERitual = fakeDkgTDecFlowE2e(variant);
+ const fakeRitual = fakeDkgRitual(fakeE2ERitual);
const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const initRitualSpy = mockInitializeRitual(fakeRitual);
const testCohort = await Cohort.create(cohortConfig);
- const testStrategy = CbdStrategy.create(
- testCohort,
- undefined,
- aliceSecretKey
- );
+ const testStrategy = CbdStrategy.create(testCohort, undefined);
const testDeployed = await testStrategy.deploy(aliceProvider);
expect(testDeployed.dkgRitual.id).toEqual(fakeRitual.id);
expect(getUrsulasSpy).toHaveBeenCalled();
@@ -110,49 +107,57 @@ describe('CbdDeployedStrategy', () => {
porterUri: 'https://_this.should.crash',
};
const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
- const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
afterEach(() => {
jest.restoreAllMocks();
});
- // TODO: Update this test
- // it('can export to JSON', async () => {
- // const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
- // const mockedUrsulas = fakeUrsulas().slice(0, 3);
- // const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
- //
- // const testCohort = await Cohort.create(cohortConfig);
- // const testStrategy = CbdStrategy.create(
- // testCohort,
- // undefined,
- // bobSecretKey
- // );
- // const testDeployed = await testStrategy.deploy(aliceProvider);
- // expect(getUrsulasSpy).toHaveBeenCalled();
- //
- // const configJSON = testDeployed.toJSON();
- // expect(configJSON).toEqual(deployedStrategyJSON);
- // });
+ it('can import from JSON', async () => {
+ const json = JSON.stringify(deployedCbdStrategyObj);
+ const importedStrategy = DeployedCbdStrategy.fromJSON(json);
+ const configJSON = importedStrategy.toJSON();
+ expect(configJSON).toEqual(json);
+ });
- // TODO: Update this test
- // it('can import from JSON', async () => {
- // const importedStrategy = DeployedCbdStrategy.fromJSON(deployedStrategyJSON);
- // const configJSON = importedStrategy.toJSON();
- // expect(configJSON).toEqual(deployedStrategyJSON);
- // });
+ it('can export to JSON', async () => {
+ const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
+ const mockedUrsulas = fakeUrsulas().slice(0, 3);
+ const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
+ const fakeDkg = fakeDkgFlow(FerveoVariant.Precomputed, 0);
+ const fakeRitual = fakeDkgRitual(fakeDkg);
+ const initializeRitualSpy = mockInitializeRitual(fakeRitual);
+
+ const testCohort = await Cohort.create(cohortConfig);
+ const testStrategy = CbdStrategy.create(testCohort, undefined);
+ const testDeployed = await testStrategy.deploy(aliceProvider);
+ expect(getUrsulasSpy).toHaveBeenCalled();
+ expect(initializeRitualSpy).toHaveBeenCalled();
+
+ const asJson = testDeployed.toJSON();
+ expect(asJson).toBeDefined();
+ const asObj = JSON.parse(asJson);
+ // TODO: Will not match until we hardcode validator keypairs in tests
+ // expect(asJson).toEqual(deployedCbdStrategyJSON);
+ // So instead we do:
+ delete asObj.dkgRitual.dkgPublicKey;
+ const expectedObj: Partial = Object.assign(
+ deployedCbdStrategyObj
+ );
+ delete expectedObj.dkgRitual.dkgPublicKey;
+ expect(asObj).toEqual(expectedObj);
+ });
it('can encrypt and decrypt', async () => {
const variant = FerveoVariant.Precomputed;
- const fakeRitual = fakeDkgRitual(variant);
- const { decryptionShares } = fakeDkgRitualE2e(variant);
+ const fakeDkg = fakeDkgFlow(variant, 0);
+ const fakeRitual = fakeDkgRitual(fakeDkg);
const web3Provider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
const mockedUrsulas = fakeUrsulas().slice(0, 3);
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const initializeRitualSpy = mockInitializeRitual(fakeRitual);
const cohort = await Cohort.create(cohortConfig);
- const strategy = CbdStrategy.create(cohort, undefined, bobSecretKey);
+ const strategy = CbdStrategy.create(cohort, undefined);
const deployedStrategy = await strategy.deploy(web3Provider);
expect(getUrsulasSpy).toHaveBeenCalled();
@@ -168,13 +173,20 @@ describe('CbdDeployedStrategy', () => {
});
const conditionSet = new ConditionSet([ownsNFT]);
- const plaintext = 'this is a secret';
+ const message = 'this is a secret';
const { ciphertext, aad } = encrypter.encryptMessageCbd(
- plaintext,
+ message,
conditionSet
);
// Setup mocks for `retrieveAndDecrypt`
+ const { decryptionShares } = fakeTDecFlow({
+ ...fakeDkg,
+ variant,
+ message: toBytes(message),
+ aad,
+ ciphertext,
+ });
const getUrsulasSpy2 = mockGetUrsulas(mockedUrsulas);
const decryptSpy = mockDecrypt(decryptionShares);
@@ -188,22 +200,23 @@ describe('CbdDeployedStrategy', () => {
);
expect(getUrsulasSpy2).toHaveBeenCalled();
expect(decryptSpy).toHaveBeenCalled();
- expect(decryptedMessage[0]).toEqual(toBytes(plaintext));
+ expect(decryptedMessage[0]).toEqual(toBytes(message));
});
});
-// TODO: Update this test
describe('cbd tdec decrypter', () => {
- // const importedStrategy = DeployedCbdStrategy.fromJSON(deployedStrategyJSON);
- //
- // it('can export to JSON', () => {
- // const configJSON = importedStrategy.decrypter.toJSON();
- // expect(configJSON).toEqual(decrypterJSON);
- // });
- //
- // it('can import from JSON', () => {
- // const decrypter = PreTDecDecrypter.fromJSON(decrypterJSON);
- // const configJSON = decrypter.toJSON();
- // expect(configJSON).toEqual(decrypterJSON);
- // });
+ const importedStrategy = DeployedCbdStrategy.fromJSON(
+ JSON.stringify(deployedCbdStrategyObj)
+ );
+
+ it('can export to JSON', () => {
+ const configJSON = importedStrategy.decrypter.toJSON();
+ expect(configJSON).toEqual(cbdDecrypterJSON);
+ });
+
+ it('can import from JSON', () => {
+ const decrypter = CbdTDecDecrypter.fromJSON(cbdDecrypterJSON);
+ const configJSON = decrypter.toJSON();
+ expect(configJSON).toEqual(cbdDecrypterJSON);
+ });
});
diff --git a/test/unit/pre-strategy.test.ts b/test/unit/pre-strategy.test.ts
index b28d68b55..4cbd38143 100644
--- a/test/unit/pre-strategy.test.ts
+++ b/test/unit/pre-strategy.test.ts
@@ -27,7 +27,7 @@ import {
import {
aliceSecretKeyBytes,
bobSecretKeyBytes,
- deployedStrategyJSON,
+ deployedPreStrategyJSON,
encryptedTreasureMapBase64,
} from './testVariables';
@@ -50,17 +50,6 @@ const conditionSet = new ConditionSet([ownsNFT]);
const mockedUrsulas = fakeUrsulas().slice(0, 3);
describe('PreStrategy', () => {
- const cohortConfig = {
- threshold: 2,
- shares: 3,
- porterUri: 'https://_this.should.crash',
- };
- const aliceSecretKey = SecretKey.fromBEBytes(aliceSecretKeyBytes);
- const bobSecretKey = SecretKey.fromBEBytes(bobSecretKeyBytes);
- const aliceProvider = fakeWeb3Provider(aliceSecretKey.toBEBytes());
- Date.now = jest.fn(() => 1487076708000);
-
-describe('Strategy', () => {
afterEach(() => {
jest.restoreAllMocks();
});
@@ -227,7 +216,9 @@ describe('PreDeployedStrategy', () => {
});
describe('pre tdec decrypter', () => {
- const decrypter = DeployedPreStrategy.fromJSON(deployedStrategyJSON).decrypter;
+ const decrypter = DeployedPreStrategy.fromJSON(
+ deployedPreStrategyJSON
+ ).decrypter;
it('serializes to JSON', () => {
const asJson = decrypter.toJSON();
diff --git a/test/unit/testVariables.ts b/test/unit/testVariables.ts
index a1a6c3b7e..7e6fad8bd 100644
--- a/test/unit/testVariables.ts
+++ b/test/unit/testVariables.ts
@@ -1,4 +1,4 @@
-export const strategyJSON = JSON.stringify({
+export const preStrategyJSON = JSON.stringify({
cohort: {
ursulaAddresses: [
'0x5cf1703a1c99a4b42eb056535840e93118177232',
@@ -15,10 +15,23 @@ export const strategyJSON = JSON.stringify({
endDate: '2123-03-16T12:51:48.000Z',
});
+export const cbdStrategyJSON = JSON.stringify({
+ cohort: {
+ ursulaAddresses: [
+ '0x5cf1703a1c99a4b42eb056535840e93118177232',
+ '0x7fff551249d223f723557a96a0e1a469c79cc934',
+ '0x9c7c824239d3159327024459ad69bb215859bd25',
+ ],
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ },
+});
+
export const encryptedTreasureMapBase64 =
'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';
-export const deployedStrategyJSON = JSON.stringify({
+export const deployedPreStrategyJSON = JSON.stringify({
policy: {
id: 'base64:tKuR/HipMeU4trCdytbZCQ==',
label: 'test',
@@ -43,6 +56,26 @@ export const deployedStrategyJSON = JSON.stringify({
},
bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
});
+
+export const deployedCbdStrategyObj = {
+ dkgRitual: {
+ id: 1,
+ dkgPublicKey:
+ 'base64:MAAAAAAAAACGxOoiK8/cO6vl2gb12nlQSFgUP+Mo5OHt6vhBqlMsOzWiSuejdy2z3AxAnz2Du8k=',
+ dkgPublicParams:
+ 'base64:MAAAAAAAAAC38dOnMZfXlCaVY4xPqawPw2iMT5d0uQWhTjo/FxusWGxV6D/5ehrv+zrwCtsixruIAAAAAAAAAAQAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA3YCAAPs0AQDds7MUY0AAAAAAAAAAAAAAAD//////lv+/wKkvVMF2KEJCNg5M0h9nSlTp+1zAQAAAP///v/+W/uJAKS6ZzTTnpM5C+ilR32dKVOn7XM=',
+ },
+ cohortConfig: {
+ ursulaAddresses: [
+ '0x5cf1703a1c99a4b42eb056535840e93118177232',
+ '0x7fff551249d223f723557a96a0e1a469c79cc934',
+ '0x9c7c824239d3159327024459ad69bb215859bd25',
+ ],
+ threshold: 2,
+ shares: 3,
+ porterUri: 'https://_this.should.crash',
+ },
+};
export const aliceSecretKeyBytes = new Uint8Array([
55, 82, 190, 189, 203, 164, 60, 148, 36, 86, 46, 123, 63, 152, 215, 113, 174,
86, 244, 44, 23, 227, 197, 68, 5, 85, 116, 31, 208, 152, 88, 53,
@@ -53,7 +86,7 @@ export const bobSecretKeyBytes = new Uint8Array([
229, 2, 106, 176, 205, 33, 168, 23, 213, 233, 200, 238, 11, 193, 153,
]);
-export const decrypterJSON = JSON.stringify({
+export const preDecrypterJSON = JSON.stringify({
porterUri: 'https://_this.should.crash/',
policyEncryptingKeyBytes:
'base64:A/u/2+G8Hn0UPwRZqVfa41XiT/6W2+98dotTob7xKg5C',
@@ -64,6 +97,12 @@ export const decrypterJSON = JSON.stringify({
bobSecretKeyBytes: 'base64:dOs3NGmtXJMdjVMaXf3/m5PlAmqwzSGoF9XpyO4LwZk=',
});
+export const cbdDecrypterJSON = JSON.stringify({
+ porterUri: 'https://_this.should.crash/',
+ encryptingKeyBytes:
+ 'base64:MAAAAAAAAACGxOoiK8/cO6vl2gb12nlQSFgUP+Mo5OHt6vhBqlMsOzWiSuejdy2z3AxAnz2Du8k=',
+});
+
export const TEST_CONTRACT_ADDR = '0x0000000000000000000000000000000000000001';
export const TEST_CONTRACT_ADDR_2 =
'0x0000000000000000000000000000000000000002';
diff --git a/test/utils.ts b/test/utils.ts
index 5d8bfad79..cfd1a96f7 100644
--- a/test/utils.ts
+++ b/test/utils.ts
@@ -18,6 +18,7 @@ import { ethers, providers, Wallet } from 'ethers';
import { keccak256 } from 'ethers/lib/utils';
import {
AggregatedTranscript,
+ Ciphertext,
combineDecryptionSharesPrecomputed,
combineDecryptionSharesSimple,
DecryptionSharePrecomputed,
@@ -231,7 +232,12 @@ export const mockDetectEthereumProvider = () => {
});
};
-export const fakeDkgRitualE2e = (variant: FerveoVariant) => {
+export const fakeDkgFlow = (
+ variant: FerveoVariant | FerveoVariant.Precomputed,
+ tau: number,
+ sharesNum = 4,
+ threshold = 3
+) => {
if (
variant !== FerveoVariant.Simple &&
variant !== FerveoVariant.Precomputed
@@ -244,11 +250,6 @@ export const fakeDkgRitualE2e = (variant: FerveoVariant) => {
'0x' + '0'.repeat(40 - i.toString(16).length) + i.toString(16);
return EthereumAddress.fromString(ethAddr);
};
-
- const tau = 1;
- const sharesNum = 4;
- const threshold = Math.floor((sharesNum * 2) / 3);
-
const validator_keypairs: Keypair[] = [];
const validators: Validator[] = [];
for (let i = 0; i < sharesNum; i++) {
@@ -283,12 +284,46 @@ export const fakeDkgRitualE2e = (variant: FerveoVariant) => {
// Client can also aggregate the transcripts and verify them
const clientAggregate = new AggregatedTranscript(receivedMessages);
expect(clientAggregate.verify(sharesNum, receivedMessages)).toBeTruthy();
+ return {
+ tau,
+ sharesNum,
+ threshold,
+ validator_keypairs,
+ validators,
+ transcripts,
+ dkg,
+ receivedMessages,
+ serverAggregate,
+ };
+};
- // In the meantime, the client creates a ciphertext and decryption request
- const msg = Buffer.from('my-msg');
- const aad = Buffer.from('my-aad');
- const ciphertext = encrypt(msg, aad, dkg.finalKey());
-
+interface FakeDkgRitualFlow {
+ validators: Validator[];
+ validator_keypairs: Keypair[];
+ tau: number;
+ sharesNum: number;
+ threshold: number;
+ receivedMessages: ValidatorMessage[];
+ variant: FerveoVariant;
+ ciphertext: Ciphertext;
+ aad: Uint8Array;
+ dkg: Dkg;
+ message: Uint8Array;
+}
+
+export const fakeTDecFlow = ({
+ validators,
+ validator_keypairs,
+ tau,
+ sharesNum,
+ threshold,
+ receivedMessages,
+ variant,
+ ciphertext,
+ aad,
+ dkg,
+ message,
+}: FakeDkgRitualFlow) => {
// Having aggregated the transcripts, the validators can now create decryption shares
const decryptionShares: (
| DecryptionSharePrecomputed
@@ -303,7 +338,6 @@ export const fakeDkgRitualE2e = (variant: FerveoVariant) => {
}
let decryptionShare;
-
if (variant === FerveoVariant.Precomputed) {
decryptionShare = aggregate.createDecryptionSharePrecomputed(
dkg,
@@ -342,29 +376,41 @@ export const fakeDkgRitualE2e = (variant: FerveoVariant) => {
sharedSecret,
dkg.publicParams()
);
- if (!bytesEqual(plaintext, msg)) {
+ if (!bytesEqual(plaintext, message)) {
throw new Error('Decryption failed');
}
+ return { decryptionShares, sharedSecret, plaintext };
+};
+
+export const fakeDkgTDecFlowE2e = (
+ variant: FerveoVariant,
+ message = toBytes('fake-message'),
+ aad = toBytes('fake-aad'),
+ ritualId = 0
+) => {
+ const ritual = fakeDkgFlow(variant, ritualId, 4, 3);
+
+ // In the meantime, the client creates a ciphertext and decryption request
+ const ciphertext = encrypt(message, aad, ritual.dkg.finalKey());
+ const { decryptionShares } = fakeTDecFlow({
+ ...ritual,
+ variant,
+ ciphertext,
+ aad,
+ message,
+ });
return {
- tau,
- sharesNum,
- threshold,
- validator_keypairs,
- validators,
- transcripts,
- dkg,
- receivedMessages,
- msg,
+ ...ritual,
+ message,
aad,
ciphertext,
- serverAggregate,
decryptionShares,
};
};
export const fakeCoordinatorRitual = (ritualId: number): CoordinatorRitual => {
- const ritual = fakeDkgRitualE2e(FerveoVariant.Precomputed);
+ const ritual = fakeDkgTDecFlowE2e(FerveoVariant.Precomputed);
return {
id: ritualId,
initiator: ritual.validators[0].address.toString(),
@@ -381,7 +427,7 @@ export const fakeCoordinatorRitual = (ritualId: number): CoordinatorRitual => {
};
export const fakeDkgParticipants = (): DkgParticipant[] => {
- const ritual = fakeDkgRitualE2e(FerveoVariant.Precomputed);
+ const ritual = fakeDkgTDecFlowE2e(FerveoVariant.Precomputed);
return zip(
zip(ritual.validators, ritual.transcripts),
ritual.validator_keypairs
@@ -406,8 +452,7 @@ export const mockDecrypt = (
});
};
-export const fakeDkgRitual = (variant: FerveoVariant) => {
- const ritual = fakeDkgRitualE2e(variant);
+export const fakeDkgRitual = (ritual: { dkg: Dkg }) => {
return new DkgRitual(1, ritual.dkg.finalKey(), ritual.dkg.publicParams());
};
From e08197ddf6a6dc183f19bc92386ddb5595eaa88f Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Tue, 23 May 2023 16:45:12 +0200
Subject: [PATCH 43/98] silence tsc warnings
---
src/dkg.ts | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/dkg.ts b/src/dkg.ts
index ece1d66ef..bbdc2ae0d 100644
--- a/src/dkg.ts
+++ b/src/dkg.ts
@@ -54,7 +54,9 @@ export class DkgClient {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async initializeRitual(
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
_provider: ethers.providers.Web3Provider,
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
_ritualParams: unknown
): Promise