otomato-sdk 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/examples/create-action.js +21 -0
- package/dist/examples/create-automation.js +42 -0
- package/dist/src/constants/Blocks.js +391 -0
- package/dist/src/constants/tokens.js +40 -0
- package/dist/src/index.js +3 -2
- package/dist/src/models/Action.js +6 -1
- package/dist/src/models/Automation.js +44 -1
- package/dist/src/models/Edge.js +25 -0
- package/dist/src/models/Node.js +92 -0
- package/dist/src/models/Trigger.js +3 -88
- package/dist/src/services/ApiService.js +39 -1
- package/dist/src/utils/typeValidator.js +70 -0
- package/dist/test/action.spec.js +74 -0
- package/dist/test/automation.spec.js +71 -0
- package/dist/test/node.spec.js +126 -0
- package/dist/test/trigger.spec.js +3 -3
- package/dist/test/typeValidator.spec.js +59 -0
- package/dist/types/examples/create-action.d.ts +1 -0
- package/dist/types/examples/create-automation.d.ts +1 -0
- package/dist/types/src/constants/Blocks.d.ts +118 -0
- package/dist/types/src/constants/tokens.d.ts +9 -0
- package/dist/types/src/index.d.ts +3 -2
- package/dist/types/src/models/Action.d.ts +11 -5
- package/dist/types/src/models/Automation.d.ts +22 -5
- package/dist/types/src/models/Edge.d.ts +14 -0
- package/dist/types/src/models/Node.d.ts +42 -0
- package/dist/types/src/models/Trigger.d.ts +4 -24
- package/dist/types/src/services/ApiService.d.ts +3 -6
- package/dist/types/src/utils/typeValidator.d.ts +4 -0
- package/dist/types/test/action.spec.d.ts +1 -0
- package/dist/types/test/automation.spec.d.ts +1 -0
- package/dist/types/test/node.spec.d.ts +1 -0
- package/dist/types/test/typeValidator.spec.d.ts +1 -0
- package/examples/create-action.ts +28 -0
- package/examples/create-automation.ts +41 -0
- package/package.json +4 -3
- package/src/constants/{ActionBlocks.ts → Blocks.ts} +73 -2
- package/src/constants/chains.ts +1 -1
- package/src/constants/json.json +16 -0
- package/src/constants/tokens.ts +56 -0
- package/src/index.ts +3 -2
- package/src/models/Action.ts +8 -6
- package/src/models/Automation.ts +47 -6
- package/src/models/Edge.ts +33 -0
- package/src/models/Node.ts +118 -0
- package/src/models/Trigger.ts +5 -101
- package/src/services/ApiService.ts +31 -6
- package/src/utils/typeValidator.ts +65 -0
- package/test/action.spec.ts +90 -0
- package/test/automation.spec.ts +88 -0
- package/test/node.spec.ts +143 -0
- package/test/trigger.spec.ts +3 -3
- package/test/typeValidator.spec.ts +71 -0
- package/src/services/AutomationService.ts +0 -6
|
@@ -1,23 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export class Trigger {
|
|
1
|
+
import { Node } from './Node.js';
|
|
2
|
+
export class Trigger extends Node {
|
|
3
3
|
constructor(trigger) {
|
|
4
|
-
|
|
5
|
-
this.name = trigger.name;
|
|
6
|
-
this.description = trigger.description;
|
|
4
|
+
super(Object.assign(Object.assign({}, trigger), { class: 'trigger' }));
|
|
7
5
|
this.type = trigger.type;
|
|
8
|
-
this.parameters = {};
|
|
9
|
-
this.keyMap = {};
|
|
10
|
-
trigger.parameters.forEach(param => {
|
|
11
|
-
this.parameters[param.key] = Object.assign(Object.assign({}, param), { value: null });
|
|
12
|
-
const simplifiedKey = this.getSimplifiedKey(param.key);
|
|
13
|
-
this.keyMap[simplifiedKey] = param.key;
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
setChainId(value) {
|
|
17
|
-
this.setParameter('chainId', value);
|
|
18
|
-
}
|
|
19
|
-
setContractAddress(value) {
|
|
20
|
-
this.setParameter('contractAddress', value);
|
|
21
6
|
}
|
|
22
7
|
setCondition(value) {
|
|
23
8
|
if (this.type !== 1) {
|
|
@@ -37,74 +22,4 @@ export class Trigger {
|
|
|
37
22
|
}
|
|
38
23
|
this.setParameter('interval', value);
|
|
39
24
|
}
|
|
40
|
-
setParams(key, value) {
|
|
41
|
-
const fullKey = `abiParams.${key}`;
|
|
42
|
-
if (fullKey in this.parameters) {
|
|
43
|
-
this.setParameter(fullKey, value);
|
|
44
|
-
}
|
|
45
|
-
else {
|
|
46
|
-
throw new Error(`Parameter with simplified key ${key} not found in abiParams`);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
setParameter(key, value) {
|
|
50
|
-
if (key in this.parameters) {
|
|
51
|
-
const param = this.parameters[key];
|
|
52
|
-
if (this.validateType(param.type, value)) {
|
|
53
|
-
this.parameters[key].value = value;
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
throw new Error(`Invalid type for parameter ${key}. Expected ${param.type}.`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
else {
|
|
60
|
-
throw new Error(`Parameter with key ${key} not found`);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
validateType(expectedType, value) {
|
|
64
|
-
switch (expectedType) {
|
|
65
|
-
case 'int':
|
|
66
|
-
case 'integer':
|
|
67
|
-
case 'uint256':
|
|
68
|
-
case 'int256':
|
|
69
|
-
return Number.isInteger(value);
|
|
70
|
-
case 'address':
|
|
71
|
-
return typeof value === 'string' && this.isAddress(value);
|
|
72
|
-
case 'float':
|
|
73
|
-
return typeof value === 'number';
|
|
74
|
-
case 'logic_operator':
|
|
75
|
-
const validOperators = new Set(['<', '>', '<=', '>=', '==']);
|
|
76
|
-
return typeof value === 'string' && validOperators.has(value);
|
|
77
|
-
case 'any':
|
|
78
|
-
return true;
|
|
79
|
-
default:
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
isAddress(value) {
|
|
84
|
-
return ethers.isAddress(value);
|
|
85
|
-
}
|
|
86
|
-
getParameter(key) {
|
|
87
|
-
if (key in this.parameters) {
|
|
88
|
-
return this.parameters[key].value;
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
throw new Error(`Parameter with key ${key} not found`);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
getParameters() {
|
|
95
|
-
return Object.keys(this.parameters).reduce((acc, key) => {
|
|
96
|
-
acc[key] = this.parameters[key].value;
|
|
97
|
-
return acc;
|
|
98
|
-
}, {});
|
|
99
|
-
}
|
|
100
|
-
toJSON() {
|
|
101
|
-
const json = {
|
|
102
|
-
id: this.id,
|
|
103
|
-
parameters: this.getParameters(),
|
|
104
|
-
};
|
|
105
|
-
return json;
|
|
106
|
-
}
|
|
107
|
-
getSimplifiedKey(key) {
|
|
108
|
-
return key.replace(/[.\[\]]/g, '_');
|
|
109
|
-
}
|
|
110
25
|
}
|
|
@@ -1 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
// networkService.ts
|
|
11
|
+
import axios from 'axios';
|
|
12
|
+
const API_CONFIG = {
|
|
13
|
+
BASE_URL: 'http://localhost:3040/api',
|
|
14
|
+
HEADERS: {
|
|
15
|
+
'Content-Type': 'application/json'
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const axiosInstance = axios.create({
|
|
19
|
+
baseURL: API_CONFIG.BASE_URL,
|
|
20
|
+
headers: API_CONFIG.HEADERS
|
|
21
|
+
});
|
|
22
|
+
export const apiServices = {
|
|
23
|
+
post(endpoint, data) {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
try {
|
|
26
|
+
const response = yield axiosInstance.post(endpoint, data);
|
|
27
|
+
return response.data;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
console.error('Network request failed', error);
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
// Add other HTTP methods if needed
|
|
36
|
+
// async get(endpoint: string) { ... }
|
|
37
|
+
// async put(endpoint: string, data: any) { ... }
|
|
38
|
+
// async delete(endpoint: string) { ... }
|
|
39
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { ethers } from 'ethers';
|
|
2
|
+
export function validateType(expectedType, value) {
|
|
3
|
+
switch (expectedType) {
|
|
4
|
+
case 'bool':
|
|
5
|
+
case 'boolean':
|
|
6
|
+
return typeof value === 'boolean';
|
|
7
|
+
case 'chainId':
|
|
8
|
+
case 'integer':
|
|
9
|
+
return Number.isInteger(value);
|
|
10
|
+
case 'int8':
|
|
11
|
+
case 'int16':
|
|
12
|
+
case 'int32':
|
|
13
|
+
case 'int64':
|
|
14
|
+
case 'int128':
|
|
15
|
+
case 'int256':
|
|
16
|
+
return Number.isInteger(value) && isIntInRange(value, parseInt(expectedType.replace('int', '')));
|
|
17
|
+
case 'uint8':
|
|
18
|
+
case 'uint16':
|
|
19
|
+
case 'uint32':
|
|
20
|
+
case 'uint64':
|
|
21
|
+
case 'uint128':
|
|
22
|
+
case 'uint256':
|
|
23
|
+
return Number.isInteger(value) && isUintInRange(value, parseInt(expectedType.replace('uint', '')));
|
|
24
|
+
case 'erc20':
|
|
25
|
+
case 'nftCollection':
|
|
26
|
+
case 'address':
|
|
27
|
+
return typeof value === 'string' && isAddress(value);
|
|
28
|
+
case 'float':
|
|
29
|
+
case 'fixed':
|
|
30
|
+
case 'ufixed':
|
|
31
|
+
return typeof value === 'number';
|
|
32
|
+
case 'url':
|
|
33
|
+
return typeof value === 'string' && isValidUrl(value);
|
|
34
|
+
case 'phone_number':
|
|
35
|
+
return typeof value === 'string' && isValidPhoneNumber(value);
|
|
36
|
+
case 'paragraph':
|
|
37
|
+
return typeof value === 'string';
|
|
38
|
+
case 'logic_operator':
|
|
39
|
+
const validOperators = new Set(['<', '>', '<=', '>=', '==', '!=']);
|
|
40
|
+
return typeof value === 'string' && validOperators.has(value);
|
|
41
|
+
case 'any':
|
|
42
|
+
return true;
|
|
43
|
+
default:
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function isIntInRange(value, bits) {
|
|
48
|
+
const min = -(Math.pow(2, (bits - 1)));
|
|
49
|
+
const max = (Math.pow(2, (bits - 1))) - 1;
|
|
50
|
+
return value >= min && value <= max;
|
|
51
|
+
}
|
|
52
|
+
function isUintInRange(value, bits) {
|
|
53
|
+
const max = (Math.pow(2, bits)) - 1;
|
|
54
|
+
return value >= 0 && value <= max;
|
|
55
|
+
}
|
|
56
|
+
export function isAddress(value) {
|
|
57
|
+
return ethers.isAddress(value);
|
|
58
|
+
}
|
|
59
|
+
export function isValidUrl(value) {
|
|
60
|
+
try {
|
|
61
|
+
new URL(value);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch (_) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
export function isValidPhoneNumber(value) {
|
|
69
|
+
return /^[\+]?[0-9]{0,3}\W?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/im.test(value);
|
|
70
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { Action, ACTIONS, getToken, CHAINS } from '../src/index';
|
|
3
|
+
const DEFAULT_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
4
|
+
describe('Action Class', () => {
|
|
5
|
+
it('should create a transfer action without parameters', () => {
|
|
6
|
+
const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
|
|
7
|
+
const params = transferAction.getParameters();
|
|
8
|
+
expect(params.chainId).to.be.null;
|
|
9
|
+
expect(params['abiParams.value']).to.be.null;
|
|
10
|
+
expect(params['abiParams.to']).to.be.null;
|
|
11
|
+
expect(params.contractAddress).to.be.null;
|
|
12
|
+
});
|
|
13
|
+
it('should create a transfer action and set parameters correctly', () => {
|
|
14
|
+
const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
|
|
15
|
+
transferAction.setChainId(CHAINS.ETHEREUM);
|
|
16
|
+
transferAction.setParams("value", 1000);
|
|
17
|
+
transferAction.setParams("to", DEFAULT_ADDRESS);
|
|
18
|
+
transferAction.setContractAddress(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
19
|
+
const params = transferAction.getParameters();
|
|
20
|
+
expect(params.chainId).to.equal(CHAINS.ETHEREUM);
|
|
21
|
+
expect(params['abiParams.value']).to.equal(1000);
|
|
22
|
+
expect(params['abiParams.to']).to.equal(DEFAULT_ADDRESS);
|
|
23
|
+
expect(params.contractAddress).to.equal(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
24
|
+
});
|
|
25
|
+
it('should be able to export an action as json', () => {
|
|
26
|
+
const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
|
|
27
|
+
transferAction.setChainId(CHAINS.ETHEREUM);
|
|
28
|
+
transferAction.setParams("value", 1000);
|
|
29
|
+
transferAction.setParams("to", DEFAULT_ADDRESS);
|
|
30
|
+
transferAction.setContractAddress(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
31
|
+
const json = transferAction.toJSON();
|
|
32
|
+
expect(json).to.deep.equal({
|
|
33
|
+
id: ACTIONS.TOKENS.ERC20.TRANSFER.id,
|
|
34
|
+
parameters: {
|
|
35
|
+
chainId: CHAINS.ETHEREUM,
|
|
36
|
+
'abiParams.value': 1000,
|
|
37
|
+
'abiParams.to': DEFAULT_ADDRESS,
|
|
38
|
+
contractAddress: getToken(CHAINS.ETHEREUM, 'USDC').contractAddress
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it('should create an SMS action and set parameters correctly', () => {
|
|
43
|
+
const smsAction = new Action(ACTIONS.NOTIFICATIONS.SMS);
|
|
44
|
+
smsAction.setParams("phoneNumber", "+1234567890");
|
|
45
|
+
smsAction.setParams("text", "Hello, this is a test message!");
|
|
46
|
+
const params = smsAction.getParameters();
|
|
47
|
+
expect(params.phoneNumber).to.equal("+1234567890");
|
|
48
|
+
expect(params.text).to.equal("Hello, this is a test message!");
|
|
49
|
+
});
|
|
50
|
+
it('should create a Slack action and set parameters correctly', () => {
|
|
51
|
+
const slackAction = new Action(ACTIONS.NOTIFICATIONS.SLACK);
|
|
52
|
+
slackAction.setParams("webhook", "https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX");
|
|
53
|
+
slackAction.setParams("text", "This is a test message!");
|
|
54
|
+
const params = slackAction.getParameters();
|
|
55
|
+
expect(params.webhook).to.equal("https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX");
|
|
56
|
+
expect(params.text).to.equal("This is a test message!");
|
|
57
|
+
});
|
|
58
|
+
it('should throw an error for invalid parameter type', () => {
|
|
59
|
+
const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
|
|
60
|
+
expect(() => transferAction.setParams("value", "invalid")).to.throw('Invalid type for parameter abiParams.value. Expected uint256.');
|
|
61
|
+
});
|
|
62
|
+
it('should throw an error for invalid address', () => {
|
|
63
|
+
const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
|
|
64
|
+
expect(() => transferAction.setParams("to", "invalid_address")).to.throw('Invalid type for parameter abiParams.to. Expected address.');
|
|
65
|
+
});
|
|
66
|
+
it('should throw an error for invalid URL', () => {
|
|
67
|
+
const slackAction = new Action(ACTIONS.NOTIFICATIONS.SLACK);
|
|
68
|
+
expect(() => slackAction.setParams("webhook", "invalid_url")).to.throw('Invalid type for parameter webhook. Expected url.');
|
|
69
|
+
});
|
|
70
|
+
it('should throw an error for invalid phone number', () => {
|
|
71
|
+
const smsAction = new Action(ACTIONS.NOTIFICATIONS.SMS);
|
|
72
|
+
expect(() => smsAction.setParams("phoneNumber", "invalid_phone_number")).to.throw('Invalid type for parameter phoneNumber. Expected phone_number.');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { Automation } from '../src/models/Automation.js';
|
|
3
|
+
import { Trigger } from '../src/models/Trigger.js';
|
|
4
|
+
import { Action } from '../src/models/Action.js';
|
|
5
|
+
import { TRIGGERS, ACTIONS, getToken, CHAINS } from '../src/index.js';
|
|
6
|
+
describe('Automation Class', () => {
|
|
7
|
+
it('should create an automation with a trigger and actions', () => {
|
|
8
|
+
const trigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
|
|
9
|
+
trigger.setChainId(CHAINS.ETHEREUM);
|
|
10
|
+
trigger.setContractAddress(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
11
|
+
trigger.setPosition(0, 0);
|
|
12
|
+
const action1 = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
|
|
13
|
+
action1.setChainId(CHAINS.ETHEREUM);
|
|
14
|
+
action1.setParams("value", 1000);
|
|
15
|
+
action1.setParams("to", "0xe1432599B51d9BE1b5A27E2A2FB8e5dF684749C6");
|
|
16
|
+
action1.setContractAddress(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
17
|
+
action1.setPosition(1, 0);
|
|
18
|
+
const action2 = new Action(ACTIONS.NOTIFICATIONS.SMS);
|
|
19
|
+
action2.setParams("phoneNumber", "+1234567890");
|
|
20
|
+
action2.setParams("text", "This is a test message");
|
|
21
|
+
action2.setPosition(2, 0);
|
|
22
|
+
const automation = new Automation("Test Automation", [trigger, action1, action2]);
|
|
23
|
+
const json = automation.toJSON();
|
|
24
|
+
expect(json).to.deep.equal({
|
|
25
|
+
name: "Test Automation",
|
|
26
|
+
nodes: [trigger.toJSON(), action1.toJSON(), action2.toJSON()],
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
it('should set the name of the automation', () => {
|
|
30
|
+
const trigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
|
|
31
|
+
trigger.setChainId(CHAINS.ETHEREUM);
|
|
32
|
+
trigger.setContractAddress(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
33
|
+
trigger.setPosition(0, 0);
|
|
34
|
+
const automation = new Automation("Initial Name", [trigger]);
|
|
35
|
+
automation.setName("Updated Name");
|
|
36
|
+
expect(automation.name).to.equal("Updated Name");
|
|
37
|
+
});
|
|
38
|
+
it('should add a trigger to the automation', () => {
|
|
39
|
+
const initialTrigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
|
|
40
|
+
initialTrigger.setChainId(CHAINS.ETHEREUM);
|
|
41
|
+
initialTrigger.setContractAddress(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
42
|
+
initialTrigger.setPosition(0, 0);
|
|
43
|
+
const newTrigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
|
|
44
|
+
newTrigger.setChainId(CHAINS.ETHEREUM);
|
|
45
|
+
newTrigger.setContractAddress(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
46
|
+
newTrigger.setPosition(1, 0);
|
|
47
|
+
const automation = new Automation("Test Automation", [initialTrigger]);
|
|
48
|
+
automation.addNode(newTrigger);
|
|
49
|
+
expect(automation.nodes).to.deep.equal([initialTrigger, newTrigger]);
|
|
50
|
+
});
|
|
51
|
+
it('should add actions to the automation', () => {
|
|
52
|
+
const trigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
|
|
53
|
+
trigger.setChainId(CHAINS.ETHEREUM);
|
|
54
|
+
trigger.setContractAddress(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
55
|
+
trigger.setPosition(0, 0);
|
|
56
|
+
const action1 = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
|
|
57
|
+
action1.setChainId(CHAINS.ETHEREUM);
|
|
58
|
+
action1.setParams("value", 1000);
|
|
59
|
+
action1.setParams("to", "0xe1432599B51d9BE1b5A27E2A2FB8e5dF684749C6");
|
|
60
|
+
action1.setContractAddress(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
61
|
+
action1.setPosition(1, 0);
|
|
62
|
+
const action2 = new Action(ACTIONS.NOTIFICATIONS.SMS);
|
|
63
|
+
action2.setParams("phoneNumber", "+1234567890");
|
|
64
|
+
action2.setParams("text", "This is a test message");
|
|
65
|
+
action2.setPosition(2, 0);
|
|
66
|
+
const automation = new Automation("Test Automation", [trigger]);
|
|
67
|
+
automation.addNode(action1);
|
|
68
|
+
automation.addNode(action2);
|
|
69
|
+
expect(automation.nodes).to.deep.equal([trigger, action1, action2]);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { Node } from '../src/index'; // Adjust the import path according to your project structure
|
|
3
|
+
const DEFAULT_PARAMETERS = [
|
|
4
|
+
{ key: 'chainId', type: 'integer', description: 'Chain ID', value: null },
|
|
5
|
+
{ key: 'contractAddress', type: 'address', description: 'Contract Address', value: null }
|
|
6
|
+
];
|
|
7
|
+
describe('Node Class', () => {
|
|
8
|
+
it('should create a node without coordinates', () => {
|
|
9
|
+
const node = new Node({
|
|
10
|
+
id: 1,
|
|
11
|
+
name: 'Test Node',
|
|
12
|
+
description: 'A node for testing',
|
|
13
|
+
parameters: DEFAULT_PARAMETERS,
|
|
14
|
+
class: 'testClass'
|
|
15
|
+
});
|
|
16
|
+
expect(node.position).to.be.undefined;
|
|
17
|
+
});
|
|
18
|
+
it('should create a node with coordinates', () => {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
const node = new Node({
|
|
21
|
+
id: 2,
|
|
22
|
+
name: 'Test Node with Coordinates',
|
|
23
|
+
description: 'A node for testing with coordinates',
|
|
24
|
+
parameters: DEFAULT_PARAMETERS,
|
|
25
|
+
class: 'testClass',
|
|
26
|
+
position: { x: 100, y: 200 }
|
|
27
|
+
});
|
|
28
|
+
expect((_a = node.position) === null || _a === void 0 ? void 0 : _a.x).to.equal(100);
|
|
29
|
+
expect((_b = node.position) === null || _b === void 0 ? void 0 : _b.y).to.equal(200);
|
|
30
|
+
});
|
|
31
|
+
it('should set and get coordinates correctly', () => {
|
|
32
|
+
var _a, _b;
|
|
33
|
+
const node = new Node({
|
|
34
|
+
id: 3,
|
|
35
|
+
name: 'Test Node for Coordinates',
|
|
36
|
+
description: 'A node for testing coordinate setting',
|
|
37
|
+
parameters: DEFAULT_PARAMETERS,
|
|
38
|
+
class: 'testClass'
|
|
39
|
+
});
|
|
40
|
+
node.setPosition(300, 400);
|
|
41
|
+
expect((_a = node.position) === null || _a === void 0 ? void 0 : _a.x).to.equal(300);
|
|
42
|
+
expect((_b = node.position) === null || _b === void 0 ? void 0 : _b.y).to.equal(400);
|
|
43
|
+
});
|
|
44
|
+
it('should create a node and set parameters correctly', () => {
|
|
45
|
+
const node = new Node({
|
|
46
|
+
id: 4,
|
|
47
|
+
name: 'Test Node for Parameters',
|
|
48
|
+
description: 'A node for testing parameter setting',
|
|
49
|
+
parameters: DEFAULT_PARAMETERS,
|
|
50
|
+
class: 'testClass'
|
|
51
|
+
});
|
|
52
|
+
node.setChainId(1);
|
|
53
|
+
node.setContractAddress("0x0000000000000000000000000000000000000000");
|
|
54
|
+
const params = node.getParameters();
|
|
55
|
+
expect(params.chainId).to.equal(1);
|
|
56
|
+
expect(params.contractAddress).to.equal("0x0000000000000000000000000000000000000000");
|
|
57
|
+
});
|
|
58
|
+
it('should be able to export a node as json without coordinates', () => {
|
|
59
|
+
const node = new Node({
|
|
60
|
+
id: 5,
|
|
61
|
+
name: 'Test Node for JSON',
|
|
62
|
+
description: 'A node for testing JSON export',
|
|
63
|
+
parameters: DEFAULT_PARAMETERS,
|
|
64
|
+
class: 'testClass'
|
|
65
|
+
});
|
|
66
|
+
node.setChainId(1);
|
|
67
|
+
node.setContractAddress("0x0000000000000000000000000000000000000000");
|
|
68
|
+
const json = node.toJSON();
|
|
69
|
+
expect(json).to.deep.equal({
|
|
70
|
+
id: 5,
|
|
71
|
+
ref: node.getRef(),
|
|
72
|
+
class: 'testClass',
|
|
73
|
+
data: {
|
|
74
|
+
parameters: {
|
|
75
|
+
chainId: 1,
|
|
76
|
+
contractAddress: "0x0000000000000000000000000000000000000000"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
it('should be able to export a node as json with coordinates', () => {
|
|
82
|
+
const node = new Node({
|
|
83
|
+
id: 6,
|
|
84
|
+
name: 'Test Node for JSON with Coordinates',
|
|
85
|
+
description: 'A node for testing JSON export with coordinates',
|
|
86
|
+
parameters: DEFAULT_PARAMETERS,
|
|
87
|
+
class: 'testClass',
|
|
88
|
+
position: { x: 1, y: 2 }
|
|
89
|
+
});
|
|
90
|
+
node.setChainId(1);
|
|
91
|
+
node.setContractAddress("0x0000000000000000000000000000000000000000");
|
|
92
|
+
const json = node.toJSON();
|
|
93
|
+
expect(json).to.deep.equal({
|
|
94
|
+
id: 6,
|
|
95
|
+
ref: node.getRef(),
|
|
96
|
+
class: 'testClass',
|
|
97
|
+
data: {
|
|
98
|
+
parameters: {
|
|
99
|
+
chainId: 1,
|
|
100
|
+
contractAddress: "0x0000000000000000000000000000000000000000"
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
position: { x: 1, y: 2 }
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
it('should throw an error for invalid parameter type', () => {
|
|
107
|
+
const node = new Node({
|
|
108
|
+
id: 7,
|
|
109
|
+
name: 'Test Node for Invalid Parameter Type',
|
|
110
|
+
description: 'A node for testing invalid parameter type',
|
|
111
|
+
parameters: DEFAULT_PARAMETERS,
|
|
112
|
+
class: 'testClass'
|
|
113
|
+
});
|
|
114
|
+
expect(() => node.setParams("chainId", "invalid")).to.throw('Invalid type for parameter chainId. Expected integer.');
|
|
115
|
+
});
|
|
116
|
+
it('should throw an error for invalid address', () => {
|
|
117
|
+
const node = new Node({
|
|
118
|
+
id: 8,
|
|
119
|
+
name: 'Test Node for Invalid Address',
|
|
120
|
+
description: 'A node for testing invalid address',
|
|
121
|
+
parameters: DEFAULT_PARAMETERS,
|
|
122
|
+
class: 'testClass'
|
|
123
|
+
});
|
|
124
|
+
expect(() => node.setParams("contractAddress", "invalid_address")).to.throw('Invalid type for parameter contractAddress. Expected address.');
|
|
125
|
+
});
|
|
126
|
+
});
|
|
@@ -51,9 +51,9 @@ describe('Trigger Class', () => {
|
|
|
51
51
|
expect(params.chainId).to.equal(CHAINS.ETHEREUM);
|
|
52
52
|
expect(params['abiParams.account']).to.equal(DEFAULT_ADDRESS);
|
|
53
53
|
expect(params.contractAddress).to.equal(getToken(CHAINS.ETHEREUM, 'USDC').contractAddress);
|
|
54
|
-
expect(balanceTrigger.toJSON().condition).to.equal(">");
|
|
55
|
-
expect(balanceTrigger.toJSON().comparisonValue).to.equal(45000);
|
|
56
|
-
expect(balanceTrigger.toJSON().interval).to.equal(5000);
|
|
54
|
+
expect(balanceTrigger.toJSON().parameters.condition).to.equal(">");
|
|
55
|
+
expect(balanceTrigger.toJSON().parameters.comparisonValue).to.equal(45000);
|
|
56
|
+
expect(balanceTrigger.toJSON().parameters.interval).to.equal(5000);
|
|
57
57
|
});
|
|
58
58
|
it('should not be able to set conditions, comparison value and interval for subscription based triggers', () => {
|
|
59
59
|
const transferTrigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import { validateType } from '../src/utils/typeValidator';
|
|
3
|
+
describe('Type Validator Utility Functions', () => {
|
|
4
|
+
describe('validateType', () => {
|
|
5
|
+
it('should validate boolean values', () => {
|
|
6
|
+
expect(validateType('bool', true)).to.be.true;
|
|
7
|
+
expect(validateType('boolean', false)).to.be.true;
|
|
8
|
+
expect(validateType('bool', 'true')).to.be.false;
|
|
9
|
+
});
|
|
10
|
+
it('should validate integer values', () => {
|
|
11
|
+
expect(validateType('integer', 10)).to.be.true;
|
|
12
|
+
expect(validateType('int256', 10)).to.be.true;
|
|
13
|
+
expect(validateType('int8', 127)).to.be.true;
|
|
14
|
+
expect(validateType('int8', 128)).to.be.false;
|
|
15
|
+
expect(validateType('int8', -128)).to.be.true;
|
|
16
|
+
expect(validateType('int8', -129)).to.be.false;
|
|
17
|
+
});
|
|
18
|
+
it('should validate unsigned integer values', () => {
|
|
19
|
+
expect(validateType('uint256', 10)).to.be.true;
|
|
20
|
+
expect(validateType('uint8', 255)).to.be.true;
|
|
21
|
+
expect(validateType('uint8', 256)).to.be.false;
|
|
22
|
+
expect(validateType('uint8', -1)).to.be.false;
|
|
23
|
+
});
|
|
24
|
+
it('should validate address values', () => {
|
|
25
|
+
expect(validateType('address', '0x0000000000000000000000000000000000000000')).to.be.true;
|
|
26
|
+
expect(validateType('address', 'invalid_address')).to.be.false;
|
|
27
|
+
});
|
|
28
|
+
it('should validate float values', () => {
|
|
29
|
+
expect(validateType('float', 10.5)).to.be.true;
|
|
30
|
+
expect(validateType('fixed', 10.5)).to.be.true;
|
|
31
|
+
expect(validateType('float', '10.5')).to.be.false;
|
|
32
|
+
});
|
|
33
|
+
it('should validate URL values', () => {
|
|
34
|
+
expect(validateType('url', 'https://example.com')).to.be.true;
|
|
35
|
+
expect(validateType('url', 'invalid_url')).to.be.false;
|
|
36
|
+
});
|
|
37
|
+
it('should validate phone number values', () => {
|
|
38
|
+
expect(validateType('phone_number', '+1234567890')).to.be.true;
|
|
39
|
+
expect(validateType('phone_number', '12345')).to.be.false;
|
|
40
|
+
expect(validateType('phone_number', '+11234567890')).to.be.true;
|
|
41
|
+
expect(validateType('phone_number', '+447911123456')).to.be.true;
|
|
42
|
+
// fixme: it should not accept it
|
|
43
|
+
// expect(validateType('phone_number', '001234567890')).to.be.false;
|
|
44
|
+
});
|
|
45
|
+
it('should validate paragraph values', () => {
|
|
46
|
+
expect(validateType('paragraph', 'This is a test paragraph.')).to.be.true;
|
|
47
|
+
expect(validateType('paragraph', 12345)).to.be.false;
|
|
48
|
+
});
|
|
49
|
+
it('should validate logic operators', () => {
|
|
50
|
+
expect(validateType('logic_operator', '>')).to.be.true;
|
|
51
|
+
expect(validateType('logic_operator', 'invalid_operator')).to.be.false;
|
|
52
|
+
});
|
|
53
|
+
it('should validate any type', () => {
|
|
54
|
+
expect(validateType('any', 'any_value')).to.be.true;
|
|
55
|
+
expect(validateType('any', 12345)).to.be.true;
|
|
56
|
+
expect(validateType('any', true)).to.be.true;
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|