Skip to content

Commit b882f7e

Browse files
test(sdk): test uploadMode arweave
1 parent 89aa296 commit b882f7e

File tree

2 files changed

+322
-0
lines changed

2 files changed

+322
-0
lines changed

packages/sdk/tests/e2e/dataProtectorCore/protectData.test.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { beforeEach, describe, expect, it } from '@jest/globals';
44
import { HDNodeWallet, Wallet } from 'ethers';
55
import { IExec } from 'iexec';
66
import { SmsCallError } from 'iexec/errors';
7+
import { DEFAULT_ARWEAVE_GATEWAY } from '../../../src/config/config.js';
78
import { IExecDataProtectorCore, WorkflowError } from '../../../src/index.js';
89
import {
910
MAX_EXPECTED_BLOCKTIME,
@@ -89,6 +90,8 @@ describe('dataProtectorCore.protectData()', () => {
8990
expect(typeof result.transactionHash).toBe('string');
9091
expect(result.zipFile).toBeInstanceOf(Uint8Array);
9192
expect(typeof result.encryptionKey).toBe('string');
93+
expect(typeof result.multiaddr).toBe('string');
94+
expect(result.multiaddr.startsWith('/p2p/')).toBe(true);
9295

9396
const ethProvider = getTestRpcProvider();
9497
const iexecOptions = getTestIExecOption();
@@ -218,4 +221,94 @@ describe('dataProtectorCore.protectData()', () => {
218221
2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME
219222
);
220223
});
224+
225+
// TODO use a local service for Arweave upload API
226+
describe('when `uploadMode: "arweave"`', () => {
227+
it(
228+
'creates the protected data',
229+
async () => {
230+
// load some binary data
231+
const pngImage = await fsPromises.readFile(
232+
path.join(process.cwd(), 'tests', '_test_inputs_', 'image.png')
233+
);
234+
const data = {
235+
numberZero: 0,
236+
numberOne: 1,
237+
numberMinusOne: -1,
238+
numberPointOne: 0.1,
239+
bigintTen: BigInt(10),
240+
booleanTrue: true,
241+
booleanFalse: false,
242+
string: 'hello world!',
243+
nested: {
244+
object: {
245+
with: {
246+
binary: {
247+
data: {
248+
pngImage,
249+
},
250+
},
251+
},
252+
},
253+
},
254+
};
255+
256+
const DATA_NAME = 'test do not use';
257+
258+
const expectedSchema = {
259+
numberZero: 'f64',
260+
numberOne: 'f64',
261+
numberMinusOne: 'f64',
262+
numberPointOne: 'f64',
263+
bigintTen: 'i128',
264+
booleanTrue: 'bool',
265+
booleanFalse: 'bool',
266+
string: 'string',
267+
nested: {
268+
object: {
269+
with: {
270+
binary: {
271+
data: {
272+
pngImage: 'image/png',
273+
},
274+
},
275+
},
276+
},
277+
},
278+
};
279+
280+
const result = await dataProtectorCore.protectData({
281+
data,
282+
uploadMode: 'arweave',
283+
name: DATA_NAME,
284+
});
285+
expect(result.name).toBe(DATA_NAME);
286+
expect(typeof result.address).toBe('string');
287+
expect(result.owner).toBe(wallet.address);
288+
expect(result.schema).toStrictEqual(expectedSchema);
289+
expect(typeof result.creationTimestamp).toBe('number');
290+
expect(typeof result.transactionHash).toBe('string');
291+
expect(result.zipFile).toBeInstanceOf(Uint8Array);
292+
expect(typeof result.encryptionKey).toBe('string');
293+
expect(typeof result.multiaddr).toBe('string');
294+
expect(result.multiaddr.startsWith(DEFAULT_ARWEAVE_GATEWAY)).toBe(true);
295+
console.log(result.multiaddr);
296+
297+
const ethProvider = getTestRpcProvider();
298+
const iexecOptions = getTestIExecOption();
299+
const iexecProd = new IExec({ ethProvider }, iexecOptions);
300+
const iexecDebug = new IExec(
301+
{ ethProvider },
302+
{ ...iexecOptions, smsURL: iexecOptions.smsDebugURL }
303+
);
304+
const prodSecretPushed =
305+
await iexecProd.dataset.checkDatasetSecretExists(result.address);
306+
const debugSecretPushed =
307+
await iexecDebug.dataset.checkDatasetSecretExists(result.address);
308+
expect(prodSecretPushed).toBe(true);
309+
expect(debugSecretPushed).toBe(false);
310+
},
311+
2 * MAX_EXPECTED_BLOCKTIME + MAX_EXPECTED_WEB2_SERVICES_TIME
312+
);
313+
});
221314
});

packages/sdk/tests/unit/dataProtectorCore/protectData.test.ts

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ jest.unstable_mockModule('../../../src/services/ipfs.js', () => ({
1212
add: jest.fn(),
1313
}));
1414

15+
jest.unstable_mockModule('../../../src/services/arweave.js', () => ({
16+
add: jest.fn(),
17+
}));
18+
1519
jest.unstable_mockModule(
1620
'../../../src/lib/dataProtectorCore/smartContract/getDataProtectorCoreContract.js',
1721
() => ({
@@ -65,6 +69,11 @@ describe('protectData()', () => {
6569
'QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ'
6670
);
6771

72+
const arweave: any = await import('../../../src/services/arweave.js');
73+
arweave.add.mockResolvedValue(
74+
'gxOFCHJVJ-L310Ml6vSlk1_RoE3E3IumsFBwDigR35E'
75+
);
76+
6877
const getContractModule: any = await import(
6978
'../../../src/lib/dataProtectorCore/smartContract/getDataProtectorCoreContract.js'
7079
);
@@ -145,6 +154,28 @@ describe('protectData()', () => {
145154
});
146155
});
147156

157+
describe('When uploadMode option is invalid', () => {
158+
it('should throw a yup ValidationError with the correct message', async () => {
159+
// --- GIVEN
160+
const invalidUploadMode = 'foo';
161+
162+
await expect(
163+
// --- WHEN
164+
protectData({
165+
iexec,
166+
iexecDebug,
167+
// @ts-expect-error This is intended to actually test yup runtime validation
168+
uploadMode: invalidUploadMode,
169+
})
170+
// --- THEN
171+
).rejects.toThrow(
172+
new ValidationError(
173+
'uploadMode must be one of the following values: ipfs, arweave'
174+
)
175+
);
176+
});
177+
});
178+
148179
// TODO That should be validated at IExec SDK instantiation
149180
describe('When given IPFS node URL is NOT a proper URL', () => {
150181
it('should throw a yup ValidationError with the correct message', async () => {
@@ -667,5 +698,203 @@ describe('protectData()', () => {
667698
});
668699
});
669700
});
701+
702+
describe('when `uploadMode: "arweave"`', () => {
703+
it('should go fine and create the protected data', async () => {
704+
const pngImage = await fsPromises.readFile(
705+
path.join(process.cwd(), 'tests', '_test_inputs_', 'image.png')
706+
);
707+
const data = {
708+
numberZero: 0,
709+
numberOne: 1,
710+
numberMinusOne: -1,
711+
numberPointOne: 0.1,
712+
bigintTen: BigInt(10),
713+
booleanTrue: true,
714+
booleanFalse: false,
715+
string: 'hello world!',
716+
nested: {
717+
object: {
718+
with: {
719+
binary: {
720+
data: {
721+
pngImage,
722+
},
723+
},
724+
},
725+
},
726+
},
727+
};
728+
const DATA_NAME = 'test do not use';
729+
const expectedSchema = {
730+
numberZero: 'f64',
731+
numberOne: 'f64',
732+
numberMinusOne: 'f64',
733+
numberPointOne: 'f64',
734+
bigintTen: 'i128',
735+
booleanTrue: 'bool',
736+
booleanFalse: 'bool',
737+
string: 'string',
738+
nested: {
739+
object: {
740+
with: {
741+
binary: {
742+
data: {
743+
pngImage: 'image/png',
744+
},
745+
},
746+
},
747+
},
748+
},
749+
};
750+
const result = await protectData({
751+
iexec,
752+
iexecDebug,
753+
dataprotectorContractAddress: getRandomAddress(),
754+
...protectDataDefaultArgs,
755+
data,
756+
name: DATA_NAME,
757+
uploadMode: 'arweave',
758+
});
759+
760+
expect(result.name).toBe(DATA_NAME);
761+
expect(result.address).toBe('mockedAddress');
762+
expect(result.owner).toBe(wallet.address);
763+
expect(result.schema).toStrictEqual(expectedSchema);
764+
expect(typeof result.creationTimestamp).toBe('number');
765+
expect(result.transactionHash).toBe('mockedTxHash');
766+
expect(result.zipFile).toBeInstanceOf(Uint8Array);
767+
expect(typeof result.encryptionKey).toBe('string');
768+
769+
expect(iexec.dataset.pushDatasetSecret).toHaveBeenCalledTimes(1);
770+
expect(iexecDebug.dataset.pushDatasetSecret).toHaveBeenCalledTimes(0);
771+
});
772+
773+
it('should call the onStatusUpdate() callback function at each step', async () => {
774+
// --- GIVEN
775+
const onStatusUpdateMock = jest.fn();
776+
777+
// --- WHEN
778+
await protectData({
779+
iexec,
780+
iexecDebug,
781+
dataprotectorContractAddress: getRandomAddress(),
782+
data: { foo: 'bar' },
783+
uploadMode: 'arweave',
784+
onStatusUpdate: onStatusUpdateMock,
785+
});
786+
787+
// --- THEN
788+
expect(onStatusUpdateMock).toHaveBeenCalledTimes(14);
789+
790+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(1, {
791+
title: 'EXTRACT_DATA_SCHEMA',
792+
isDone: false,
793+
});
794+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(2, {
795+
title: 'EXTRACT_DATA_SCHEMA',
796+
isDone: true,
797+
});
798+
799+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(3, {
800+
title: 'CREATE_ZIP_FILE',
801+
isDone: false,
802+
});
803+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(4, {
804+
title: 'CREATE_ZIP_FILE',
805+
isDone: true,
806+
});
807+
808+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(5, {
809+
title: 'CREATE_ENCRYPTION_KEY',
810+
isDone: false,
811+
});
812+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(6, {
813+
title: 'CREATE_ENCRYPTION_KEY',
814+
isDone: true,
815+
payload: {
816+
encryptionKey: expect.any(String),
817+
},
818+
});
819+
820+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(7, {
821+
title: 'ENCRYPT_FILE',
822+
isDone: false,
823+
});
824+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(8, {
825+
title: 'ENCRYPT_FILE',
826+
isDone: true,
827+
});
828+
829+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(9, {
830+
title: 'UPLOAD_ENCRYPTED_FILE',
831+
isDone: false,
832+
});
833+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(10, {
834+
title: 'UPLOAD_ENCRYPTED_FILE',
835+
isDone: true,
836+
payload: {
837+
arweaveId: expect.any(String),
838+
},
839+
});
840+
841+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(11, {
842+
title: 'DEPLOY_PROTECTED_DATA',
843+
isDone: false,
844+
});
845+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(12, {
846+
title: 'DEPLOY_PROTECTED_DATA',
847+
isDone: true,
848+
payload: {
849+
address: expect.any(String),
850+
explorerUrl: expect.any(String),
851+
owner: expect.any(String),
852+
creationTimestamp: expect.any(String),
853+
txHash: expect.any(String),
854+
},
855+
});
856+
857+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(13, {
858+
title: 'PUSH_SECRET_TO_SMS',
859+
isDone: false,
860+
payload: {
861+
teeFramework: expect.any(String),
862+
},
863+
});
864+
expect(onStatusUpdateMock).toHaveBeenNthCalledWith(14, {
865+
title: 'PUSH_SECRET_TO_SMS',
866+
isDone: true,
867+
payload: {
868+
teeFramework: expect.any(String),
869+
},
870+
});
871+
});
872+
873+
describe('When upload to Arweave fails', () => {
874+
it('should throw a WorkflowError with the correct message', async () => {
875+
// --- GIVEN
876+
const arweave: any = await import('../../../src/services/arweave.js');
877+
arweave.add.mockRejectedValue(new Error('Boom Arweave'));
878+
879+
await expect(
880+
// --- WHEN
881+
protectData({
882+
iexec,
883+
iexecDebug,
884+
dataprotectorContractAddress: getRandomAddress(),
885+
...protectDataDefaultArgs,
886+
data: { foo: 'bar' },
887+
uploadMode: 'arweave',
888+
})
889+
// --- THEN
890+
).rejects.toThrow(
891+
new WorkflowError({
892+
message: 'Failed to upload encrypted data',
893+
errorCause: Error('Boom Arweave'),
894+
})
895+
);
896+
});
897+
});
898+
});
670899
});
671900
});

0 commit comments

Comments
 (0)