otomato-sdk 1.4.2 → 1.4.4

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.
Files changed (37) hide show
  1. package/dist/examples/create-action.js +1 -3
  2. package/dist/examples/create-workflow.js +12 -15
  3. package/dist/examples/load-workflow.js +5 -2
  4. package/dist/examples/test.js +59 -0
  5. package/dist/src/constants/tokens.js +55 -17
  6. package/dist/src/models/Action.js +1 -1
  7. package/dist/src/models/Edge.js +7 -3
  8. package/dist/src/models/Node.js +5 -0
  9. package/dist/src/models/Trigger.js +1 -1
  10. package/dist/src/models/Workflow.js +18 -1
  11. package/dist/src/services/ApiService.js +7 -0
  12. package/dist/test/action.spec.js +3 -0
  13. package/dist/test/node.spec.js +2 -0
  14. package/dist/test/trigger.spec.js +3 -0
  15. package/dist/test/workflow.spec.js +100 -0
  16. package/dist/types/examples/test.d.ts +1 -0
  17. package/dist/types/src/constants/tokens.d.ts +2 -0
  18. package/dist/types/src/models/Action.d.ts +2 -1
  19. package/dist/types/src/models/Edge.d.ts +1 -1
  20. package/dist/types/src/models/Node.d.ts +4 -0
  21. package/dist/types/src/models/Trigger.d.ts +2 -1
  22. package/dist/types/src/models/Workflow.d.ts +7 -8
  23. package/dist/types/src/services/ApiService.d.ts +1 -0
  24. package/dist/types/test/workflow.spec.d.ts +1 -0
  25. package/examples/create-workflow.ts +11 -13
  26. package/examples/load-workflow.ts +5 -2
  27. package/package.json +1 -1
  28. package/src/models/Action.ts +4 -3
  29. package/src/models/Edge.ts +9 -3
  30. package/src/models/Node.ts +10 -4
  31. package/src/models/Trigger.ts +4 -3
  32. package/src/models/Workflow.ts +29 -8
  33. package/src/services/ApiService.ts +6 -0
  34. package/test/action.spec.ts +3 -0
  35. package/test/node.spec.ts +2 -0
  36. package/test/trigger.spec.ts +3 -0
  37. package/test/{automation.spec.ts → workflow.spec.ts} +37 -2
@@ -1,7 +1,5 @@
1
- import { ACTIONS, getTokenFromSymbol, CHAINS, Action, TOKENS } from '../src/index.js';
1
+ import { ACTIONS, getTokenFromSymbol, CHAINS, Action } from '../src/index.js';
2
2
  const createAction = () => {
3
- console.log(TOKENS);
4
- return;
5
3
  // Create an ERC20 transfer action
6
4
  const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
7
5
  transferAction.setChainId(CHAINS.ETHEREUM);
@@ -18,40 +18,37 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
18
18
  trigger.setContractAddress(getTokenFromSymbol(CHAINS.MODE, 'WETH').contractAddress);
19
19
  trigger.setPosition(0, 0);
20
20
  const slackAction = new Action(ACTIONS.NOTIFICATIONS.SLACK.SEND_MESSAGE);
21
- slackAction.setParams("webhook", "https://hooks.slack.com/services/REPLACE_WITH_YOUR_DATA");
22
- slackAction.setParams("message", "Notification from the SDK");
21
+ slackAction.setParams("webhook", "https://hooks.slack.com/services/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");
22
+ slackAction.setParams("message", "Notification from the SDK - testing the state");
23
23
  slackAction.setPosition(0, -10);
24
- const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
24
+ /*const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
25
25
  transferAction.setChainId(CHAINS.ETHEREUM);
26
26
  transferAction.setParams("value", 1000);
27
27
  transferAction.setParams("to", "0xe1432599B51d9BE1b5A27E2A2FB8e5dF684749C6");
28
- transferAction.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
29
- const workflow = new Workflow("test from SDK", [trigger, slackAction, transferAction]);
28
+ transferAction.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);*/
29
+ const workflow = new Workflow("test from SDK", [trigger, slackAction]);
30
30
  const edge = new Edge({
31
31
  source: trigger,
32
32
  target: slackAction,
33
33
  });
34
- const edge2 = new Edge({
35
- source: slackAction,
36
- target: transferAction,
37
- });
38
34
  workflow.addEdge(edge);
39
- workflow.addEdge(edge2);
40
35
  console.log(JSON.stringify(workflow.toJSON()));
41
36
  const creationResult = yield workflow.create();
37
+ console.log(workflow.getState());
42
38
  if (!creationResult.success) {
43
39
  throw new Error("An error occurred when publishing the workflow");
44
40
  }
45
41
  console.log(workflow.id);
46
- /*const runResult = await workflow.run();
47
-
42
+ const runResult = yield workflow.run();
43
+ console.log(workflow.getState());
48
44
  if (!runResult.success) {
49
- throw new Error("An error occurred when running the workflow")
45
+ throw new Error("An error occurred when running the workflow");
50
46
  }
51
-
52
- console.log(`Workflow ${workflow.id} is running`);*/
47
+ console.log(`Workflow ${workflow.id} is running`);
48
+ console.log(workflow.getState());
53
49
  workflow.setName("ABC");
54
50
  const patchResult = yield workflow.update();
55
51
  console.log(patchResult);
52
+ console.log(workflow.getState());
56
53
  });
57
54
  main();
@@ -10,7 +10,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { Workflow, apiServices } from '../src/index.js';
11
11
  const main = () => __awaiter(void 0, void 0, void 0, function* () {
12
12
  apiServices.setAuth("eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIweDdjRUI4ZDgxNDdBYWE5ZEI4MUFjQkRGRTVjMzA1MERGQ2ZGMTg1MzciLCJzdWIiOiIweDg3RkU4YjRmMkZlODM3MGY2Y0M5YTk2MzQ0MmYwN0IwMmY0OTA5QTciLCJhdWQiOiJvdG9tYXRvLXRlc3QubmV0bGlmeS5hcHAiLCJleHAiOjE3MjMzODMxOTksIm5iZiI6MTcyMDc4OTM5OSwiaWF0IjoxNzIwNzkxMTk5LCJqdGkiOiIweDY4ZDkxOWEyMGZiYjIyNDUwZDZmOTFjMzM2ZTBmYjBjMmYyYTc3MmU3Zjg4NWU1ZjRmNzg1NTM2ZGIyYTY5YTAiLCJjdHgiOnt9fQ.MHgyOTM1NTM3MWYwOWM1YzllNWE3YjI4MjVkZTNjMDljZTkwMTQ3OTQwZmU1ZWRlMjM5YTk0MmFjYTQ5YTcwZWI0MGJlNmJiZDk2MDA4ZTIxMzJmNGM3ZTVlZGIzZDZiZjYyMDE4Mzc1MzUwMTRmNTc0ODM0ZDk4YWU3NDQwNDQzOTFi");
13
- const workflow = yield new Workflow().load("2772afe3-17b8-4e98-bdae-669adca1956d");
14
- console.log(workflow);
13
+ const workflows = yield apiServices.getWorkflowsOfUser();
14
+ // console.log(workflows);
15
+ // const workflow = await new Workflow().load(workflows[12].id);
16
+ const workflow = yield new Workflow().load("815666d5-4232-4728-953a-abde4d85c8fd");
17
+ console.log(JSON.stringify(workflow));
15
18
  });
16
19
  main();
@@ -0,0 +1,59 @@
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
+ import { ACTIONS, Action, TRIGGERS, Trigger, Workflow, CHAINS, getTokenFromSymbol, Edge, apiServices } from '../src/index.js';
11
+ const main = () => __awaiter(void 0, void 0, void 0, function* () {
12
+ apiServices.setAuth("eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIweDdjRUI4ZDgxNDdBYWE5ZEI4MUFjQkRGRTVjMzA1MERGQ2ZGMTg1MzciLCJzdWIiOiIweDg3RkU4YjRmMkZlODM3MGY2Y0M5YTk2MzQ0MmYwN0IwMmY0OTA5QTciLCJhdWQiOiJvdG9tYXRvLXRlc3QubmV0bGlmeS5hcHAiLCJleHAiOjE3MjMzODMxOTksIm5iZiI6MTcyMDc4OTM5OSwiaWF0IjoxNzIwNzkxMTk5LCJqdGkiOiIweDY4ZDkxOWEyMGZiYjIyNDUwZDZmOTFjMzM2ZTBmYjBjMmYyYTc3MmU3Zjg4NWU1ZjRmNzg1NTM2ZGIyYTY5YTAiLCJjdHgiOnt9fQ.MHgyOTM1NTM3MWYwOWM1YzllNWE3YjI4MjVkZTNjMDljZTkwMTQ3OTQwZmU1ZWRlMjM5YTk0MmFjYTQ5YTcwZWI0MGJlNmJiZDk2MDA4ZTIxMzJmNGM3ZTVlZGIzZDZiZjYyMDE4Mzc1MzUwMTRmNTc0ODM0ZDk4YWU3NDQwNDQzOTFi");
13
+ // Trigger first
14
+ const trigger = new Trigger(TRIGGERS.PRICE_ACTION.ON_CHAIN_PRICE_MOVEMENT.PRICE_MOVEMENT_AGAINST_CURRENCY);
15
+ trigger.setChainId(CHAINS.MODE);
16
+ trigger.setComparisonValue(3000);
17
+ trigger.setCondition('gte');
18
+ trigger.setParams('currency', 'USD');
19
+ trigger.setContractAddress(getTokenFromSymbol(CHAINS.MODE, 'WETH').contractAddress);
20
+ trigger.setPosition(0, 0);
21
+ const workflow = new Workflow("Test from SDK", [trigger]);
22
+ const edge = new Edge({
23
+ source: trigger,
24
+ target: trigger,
25
+ });
26
+ workflow.addEdge(edge);
27
+ const creationResult = yield workflow.create();
28
+ // Action
29
+ const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
30
+ transferAction.setChainId(CHAINS.ETHEREUM);
31
+ transferAction.setParams("value", 1000);
32
+ transferAction.setParams("to", "0xe1432599B51d9BE1b5A27E2A2FB8e5dF684749C6");
33
+ transferAction.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
34
+ // const slackAction = new Action(ACTIONS.NOTIFICATIONS.SLACK.SEND_MESSAGE);
35
+ // slackAction.setParams("webhook", "https://hooks.slack.com/services/REPLACE_WITH_YOUR_DATA");
36
+ // slackAction.setParams("message", "Notification from the SDK");
37
+ // slackAction.setPosition(0, -10);
38
+ if (!creationResult.success) {
39
+ throw new Error("An error occurred when publishing the workflow");
40
+ }
41
+ if (workflow.id) {
42
+ workflow.addNode(transferAction);
43
+ for (let i = 0; i < workflow.nodes.length; i++) {
44
+ if (workflow.nodes[i] && workflow.nodes[i + 1]) {
45
+ const edge = new Edge({
46
+ source: workflow.nodes[i],
47
+ target: workflow.nodes[i + 1],
48
+ });
49
+ workflow.addEdge(edge);
50
+ }
51
+ }
52
+ yield workflow.update();
53
+ }
54
+ if (workflow.id) {
55
+ const workflowLoaded = yield workflow.load(workflow.id);
56
+ console.log("when having Id", workflowLoaded);
57
+ }
58
+ });
59
+ main();
@@ -4,7 +4,29 @@ export const TOKENS = {
4
4
  contractAddress: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
5
5
  name: "USDC",
6
6
  symbol: "USDC",
7
- decimals: 6
7
+ decimals: 6,
8
+ image: "https://static.debank.com/image/coin/logo_url/usdc/e87790bfe0b3f2ea855dc29069b38818.png"
9
+ },
10
+ {
11
+ contractAddress: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
12
+ name: "WETH",
13
+ symbol: "WETH",
14
+ decimals: 18,
15
+ image: "https://static.debank.com/image/eth_token/logo_url/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2/61844453e63cf81301f845d7864236f6.png"
16
+ },
17
+ {
18
+ contractAddress: "0x0000000000000000000000000000000000000000",
19
+ name: "ETH",
20
+ symbol: "ETH",
21
+ decimals: 18,
22
+ image: "https://static.debank.com/image/chain/logo_url/eth/42ba589cd077e7bdd97db6480b0ff61d.png"
23
+ },
24
+ {
25
+ contractAddress: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
26
+ name: "USDT",
27
+ symbol: "USDT",
28
+ decimals: 18,
29
+ image: "https://static.debank.com/image/coin/logo_url/usdt/23af7472292cb41dc39b3f1146ead0fe.png"
8
30
  },
9
31
  ],
10
32
  34443: [
@@ -12,61 +34,71 @@ export const TOKENS = {
12
34
  contractAddress: "0x0000000000000000000000000000000000000000",
13
35
  name: "ETH",
14
36
  symbol: "ETH",
15
- decimals: 18
37
+ decimals: 18,
38
+ image: "https://static.debank.com/image/chain/logo_url/eth/42ba589cd077e7bdd97db6480b0ff61d.png"
16
39
  },
17
40
  {
18
41
  contractAddress: "0xd988097fb8612cc24eeC14542bC03424c656005f",
19
42
  name: "USDC",
20
43
  symbol: "USDC",
21
- decimals: 6
44
+ decimals: 6,
45
+ image: "https://static.debank.com/image/coin/logo_url/usdc/e87790bfe0b3f2ea855dc29069b38818.png"
22
46
  },
23
47
  {
24
48
  contractAddress: '0xcDd475325D6F564d27247D1DddBb0DAc6fA0a5CF',
25
49
  symbol: 'WBTC',
26
50
  name: 'Wrapped BTC',
27
- decimals: 8
51
+ decimals: 8,
52
+ image: "https://static.debank.com/image/eth_token/logo_url/0x2260fac5e5542a773aa44fbcfedf7c193bc2c599/d3c52e7c7449afa8bd4fad1c93f50d93.png",
28
53
  },
29
54
  {
30
55
  contractAddress: '0xf0F161fDA2712DB8b566946122a5af183995e2eD',
31
56
  symbol: 'USDT',
32
57
  name: 'USDT',
33
- decimals: 6
58
+ decimals: 6,
59
+ image: "https://static.debank.com/image/coin/logo_url/usdt/23af7472292cb41dc39b3f1146ead0fe.png"
34
60
  },
35
61
  {
36
62
  contractAddress: '0xDfc7C877a950e49D2610114102175A06C2e3167a',
37
63
  symbol: 'MODE',
38
64
  name: 'Mode',
39
- decimals: 18
65
+ decimals: 18,
66
+ image: 'https://static.debank.com/image/chain/logo_url/mode/466e6e12f4fd827f8f497cceb0601a5e.png'
40
67
  },
41
68
  {
42
69
  contractAddress: '0x71ef7EDa2Be775E5A7aa8afD02C45F059833e9d2',
43
70
  symbol: 'ionWETH',
44
71
  name: 'Ionic Wrapped Ether',
45
- decimals: 18
72
+ decimals: 18,
73
+ image: null,
46
74
  },
47
75
  {
48
76
  contractAddress: '0x4200000000000000000000000000000000000006',
49
77
  symbol: 'WETH',
50
78
  name: 'Wrapped Ether',
51
- decimals: 18
79
+ decimals: 18,
80
+ image: 'https://static.debank.com/image/mtr_token/logo_url/0x79a61d3a28f8c8537a3df63092927cfa1150fb3c/61844453e63cf81301f845d7864236f6.png'
52
81
  },
53
82
  {
54
83
  contractAddress: '0x59e710215d45F584f44c0FEe83DA6d43D762D857',
55
84
  symbol: 'ionezETH',
56
85
  name: 'Ionic Renzo Restaked ETH',
57
- decimals: 18
86
+ decimals: 18,
87
+ image: null
58
88
  },
59
89
  {
60
90
  contractAddress: '0x2416092f143378750bb29b79eD961ab195CcEea5',
61
91
  symbol: 'ezETH',
62
92
  name: 'Renzo Restaked ETH',
63
- decimals: 18
93
+ decimals: 18,
94
+ image: 'https://static.debank.com/image/mode_token/logo_url/0x2416092f143378750bb29b79ed961ab195cceea5/a66d77b85dfd99539744bc62966e1fac.png'
64
95
  },
65
96
  {
66
97
  contractAddress: '0x9c29a8eC901DBec4fFf165cD57D4f9E03D4838f7',
67
98
  symbol: 'ironETH',
68
99
  name: 'Ironclad ETH',
69
- decimals: 18
100
+ decimals: 18,
101
+ image: null
70
102
  },
71
103
  ]
72
104
  };
@@ -74,29 +106,35 @@ export const NFTS = {
74
106
  1: [
75
107
  {
76
108
  contractAddress: "0x60e4d786628fea6478f785a6d7e704777c86a7c6",
77
- name: "MutantApeYachtClub"
109
+ name: "MutantApeYachtClub",
110
+ image: "https://images.blur.io/_blur-prod/0x60e4d786628fea6478f785a6d7e704777c86a7c6/4647-3c64c4804b4cd5fe?w=128"
78
111
  },
79
112
  {
80
113
  contractAddress: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
81
- name: "BoredApeYachtClub"
114
+ name: "BoredApeYachtClub",
115
+ image: "https://images.blur.io/_blur-prod/0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d/8321-69a4c46a6e8e5b07?w=128"
82
116
  },
83
117
  {
84
118
  contractAddress: "0xbd3531da5cf5857e7cfaa92426877b022e612cf8",
85
- name: "Pudgy Penguins"
119
+ name: "Pudgy Penguins",
120
+ image: "https://images.blur.io/_blur-prod/0xbd3531da5cf5857e7cfaa92426877b022e612cf8/760-b91995265fdeb95a?w=128"
86
121
  },
87
122
  {
88
123
  contractAddress: "0x8a90cab2b38dba80c64b7734e58ee1db38b8992e",
89
- name: "Doodles"
124
+ name: "Doodles",
125
+ image: "https://images.blur.io/_blur-prod/0x8a90cab2b38dba80c64b7734e58ee1db38b8992e/7522-a0e3ae3f8d77961e?w=128"
90
126
  },
91
127
  {
92
128
  contractAddress: "0x524cab2ec69124574082676e6f654a18df49a048",
93
- name: "Lil Pudgies"
129
+ name: "Lil Pudgies",
130
+ image: "https://images.blur.io/_blur-prod/0x524cab2ec69124574082676e6f654a18df49a048/17176-05eebb761a566d53?w=128"
94
131
  },
95
132
  ],
96
133
  34443: [
97
134
  {
98
135
  contractAddress: "0x2ad86eeec513ac16804bb05310214c3fd496835b",
99
- name: "Space id"
136
+ name: "Space id",
137
+ image: "https://s.nfte.so/asset/collection/featured/4e4e0173-77d8-42fd-86a5-b5ab4a6ac394.png?x-oss-process=image/resize,m_fill,w_300,h_300,type_6/ignore-error,1"
100
138
  }
101
139
  ]
102
140
  };
@@ -20,7 +20,7 @@ export class Action extends Node {
20
20
  static fromJSON(json) {
21
21
  return __awaiter(this, void 0, void 0, function* () {
22
22
  const enriched = findActionByBlockId(json.blockId);
23
- const action = new Action(Object.assign(Object.assign({}, enriched.block), { ref: json.ref, position: json.position, parentInfo: enriched.parentInfo }));
23
+ const action = new Action(Object.assign(Object.assign({}, enriched.block), { ref: json.ref, position: json.position, parentInfo: enriched.parentInfo, state: json.state }));
24
24
  for (const [key, value] of Object.entries(json.parameters)) {
25
25
  switch (key) {
26
26
  case 'chainId':
@@ -21,10 +21,14 @@ export class Edge {
21
21
  target: this.target.getRef(),
22
22
  };
23
23
  }
24
- static fromJSON(json) {
24
+ static fromJSON(json, nodes) {
25
+ const source = nodes.find(n => n.getRef() === json.source);
26
+ const target = nodes.find(n => n.getRef() === json.target);
27
+ if (!source || !target)
28
+ throw new Error("Edge refer to non existing node");
25
29
  return new Edge({
26
- source: json.source,
27
- target: json.target,
30
+ source,
31
+ target
28
32
  });
29
33
  }
30
34
  }
@@ -22,6 +22,7 @@ export class Node {
22
22
  this.keyMap = {};
23
23
  this.class = node.class;
24
24
  this.parentInfo = node.parentInfo;
25
+ this.state = node.state || 'inactive';
25
26
  if (node.ref) {
26
27
  this.ref = node.ref;
27
28
  }
@@ -63,6 +64,9 @@ export class Node {
63
64
  getParentInfo() {
64
65
  return this.parentInfo;
65
66
  }
67
+ getState() {
68
+ return this.state;
69
+ }
66
70
  setParameter(key, value) {
67
71
  if (key in this.parameters) {
68
72
  const param = this.parameters[key];
@@ -125,6 +129,7 @@ export class Node {
125
129
  ref: this.ref,
126
130
  blockId: this.blockId,
127
131
  type: this.class,
132
+ state: this.state,
128
133
  parameters: Object.assign(Object.assign({}, this.getParameters()), staticParameters),
129
134
  };
130
135
  if (this.position) {
@@ -39,7 +39,7 @@ export class Trigger extends Node {
39
39
  static fromJSON(json) {
40
40
  return __awaiter(this, void 0, void 0, function* () {
41
41
  const enriched = findTriggerByBlockId(json.blockId);
42
- const trigger = new Trigger(Object.assign(Object.assign({}, enriched.block), { ref: json.ref, position: json.position, parentInfo: enriched.parentInfo }));
42
+ const trigger = new Trigger(Object.assign(Object.assign({}, enriched.block), { ref: json.ref, position: json.position, parentInfo: enriched.parentInfo, state: json.state }));
43
43
  for (const [key, value] of Object.entries(json.parameters)) {
44
44
  switch (key) {
45
45
  case 'chainId':
@@ -16,6 +16,7 @@ export class Workflow {
16
16
  this.name = name;
17
17
  this.nodes = nodes;
18
18
  this.edges = edges;
19
+ this.state = 'inactive';
19
20
  }
20
21
  setName(name) {
21
22
  this.name = name;
@@ -29,13 +30,27 @@ export class Workflow {
29
30
  addEdge(edge) {
30
31
  this.edges.push(edge);
31
32
  }
33
+ updateEdge(edgeId, newEdge) {
34
+ const edgeToUpdate = this.edges.find(e => e.id === edgeId);
35
+ if (edgeToUpdate) {
36
+ edgeToUpdate.source = newEdge.source;
37
+ edgeToUpdate.target = newEdge.target;
38
+ }
39
+ else {
40
+ throw new Error(`Edge with id ${edgeId} not found`);
41
+ }
42
+ }
32
43
  addEdges(edges) {
33
44
  this.edges.push(...edges);
34
45
  }
46
+ getState() {
47
+ return this.state;
48
+ }
35
49
  toJSON() {
36
50
  return {
37
51
  id: this.id,
38
52
  name: this.name,
53
+ state: this.state,
39
54
  nodes: this.nodes.map(node => node.toJSON()),
40
55
  edges: this.edges.map(edge => edge.toJSON()),
41
56
  };
@@ -94,8 +109,9 @@ export class Workflow {
94
109
  const response = yield apiServices.get(`/workflows/${workflowId}`);
95
110
  this.id = response.id;
96
111
  this.name = response.name;
112
+ this.state = response.state;
97
113
  this.nodes = yield Promise.all(response.nodes.map((nodeData) => __awaiter(this, void 0, void 0, function* () { return yield Node.fromJSON(nodeData); })));
98
- this.edges = response.edges.map((edgeData) => Edge.fromJSON(edgeData));
114
+ this.edges = response.edges.map((edgeData) => Edge.fromJSON(edgeData, this.nodes));
99
115
  return this;
100
116
  });
101
117
  }
@@ -108,6 +124,7 @@ export class Workflow {
108
124
  try {
109
125
  const response = yield apiServices.post(`/workflows/${this.id}/run`, this.toJSON());
110
126
  if (response.status === 204) {
127
+ this.state = 'active';
111
128
  return { success: true };
112
129
  }
113
130
  else {
@@ -70,5 +70,12 @@ class ApiServices {
70
70
  return response.data;
71
71
  });
72
72
  }
73
+ getWorkflowsOfUser() {
74
+ return __awaiter(this, void 0, void 0, function* () {
75
+ const headers = this.auth ? { 'Authorization': this.auth } : {};
76
+ const response = yield axiosInstance.get('/workflows', { headers });
77
+ return response.data;
78
+ });
79
+ }
73
80
  }
74
81
  export const apiServices = new ApiServices();
@@ -43,6 +43,7 @@ describe('Action Class', () => {
43
43
  ref: transferAction.getRef(),
44
44
  type: 'action',
45
45
  id: null,
46
+ state: 'inactive',
46
47
  parameters: {
47
48
  chainId: CHAINS.ETHEREUM,
48
49
  abi: {
@@ -95,6 +96,7 @@ describe('Action Class', () => {
95
96
  "ref": "n-2",
96
97
  "blockId": 100002,
97
98
  "type": "action",
99
+ "state": "inactive",
98
100
  "position": {
99
101
  "x": 0,
100
102
  "y": -10
@@ -120,6 +122,7 @@ describe('Action Class', () => {
120
122
  "ref": "n-3",
121
123
  "blockId": 100004,
122
124
  "type": "action",
125
+ "state": "inactive",
123
126
  "parameters": {
124
127
  "abi": {
125
128
  "parameters": {
@@ -69,6 +69,7 @@ describe('Node Class', () => {
69
69
  expect(json).to.deep.equal({
70
70
  blockId: 5,
71
71
  id: null,
72
+ state: 'inactive',
72
73
  ref: node.getRef(),
73
74
  type: 'action',
74
75
  parameters: {
@@ -93,6 +94,7 @@ describe('Node Class', () => {
93
94
  type: 'action',
94
95
  blockId: 6,
95
96
  id: null,
97
+ state: 'inactive',
96
98
  ref: node.getRef(),
97
99
  parameters: {
98
100
  chainId: 1,
@@ -43,6 +43,7 @@ describe('Trigger Class', () => {
43
43
  ref: transferTrigger.getRef(),
44
44
  id: null,
45
45
  type: 'trigger',
46
+ state: "inactive",
46
47
  parameters: {
47
48
  chainId: CHAINS.ETHEREUM,
48
49
  abi: {
@@ -91,6 +92,7 @@ describe('Trigger Class', () => {
91
92
  "ref": "n-1",
92
93
  "blockId": 10,
93
94
  "type": "trigger",
95
+ "state": "inactive",
94
96
  "position": {
95
97
  "x": 0,
96
98
  "y": 0
@@ -123,6 +125,7 @@ describe('Trigger Class', () => {
123
125
  "ref": "n-1",
124
126
  "blockId": 1,
125
127
  "type": "trigger",
128
+ "state": "inactive",
126
129
  "parameters": {
127
130
  "chainId": 1,
128
131
  "abi": {
@@ -0,0 +1,100 @@
1
+ import { expect } from 'chai';
2
+ import { Workflow } from '../src/models/Workflow.js';
3
+ import { Trigger } from '../src/models/Trigger.js';
4
+ import { Action } from '../src/models/Action.js';
5
+ import { TRIGGERS, ACTIONS, getTokenFromSymbol, CHAINS, Edge } from '../src/index.js';
6
+ describe('Workflow Class', () => {
7
+ it('should create a workflow with a trigger and actions', () => {
8
+ const trigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
9
+ trigger.setChainId(CHAINS.ETHEREUM);
10
+ trigger.setContractAddress(getTokenFromSymbol(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(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
17
+ action1.setPosition(1, 0);
18
+ const action2 = new Action(ACTIONS.NOTIFICATIONS.SLACK.SEND_MESSAGE);
19
+ action2.setParams("webhook", "https://webhook.url");
20
+ action2.setParams("message", "This is a test message");
21
+ action2.setPosition(2, 0);
22
+ const workflow = new Workflow("Test Workflow", [trigger, action1, action2]);
23
+ const json = workflow.toJSON();
24
+ expect(json).to.deep.equal({
25
+ name: "Test Workflow",
26
+ id: null,
27
+ nodes: [trigger.toJSON(), action1.toJSON(), action2.toJSON()],
28
+ edges: [],
29
+ state: 'inactive'
30
+ });
31
+ });
32
+ it('should set the name of the workflow', () => {
33
+ const trigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
34
+ trigger.setChainId(CHAINS.ETHEREUM);
35
+ trigger.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
36
+ trigger.setPosition(0, 0);
37
+ const workflow = new Workflow("Initial Name", [trigger]);
38
+ workflow.setName("Updated Name");
39
+ expect(workflow.name).to.equal("Updated Name");
40
+ });
41
+ it('should add a trigger to the workflow', () => {
42
+ const initialTrigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
43
+ initialTrigger.setChainId(CHAINS.ETHEREUM);
44
+ initialTrigger.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
45
+ initialTrigger.setPosition(0, 0);
46
+ const newTrigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
47
+ newTrigger.setChainId(CHAINS.ETHEREUM);
48
+ newTrigger.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
49
+ newTrigger.setPosition(1, 0);
50
+ const workflow = new Workflow("Test Workflow", [initialTrigger]);
51
+ workflow.addNode(newTrigger);
52
+ expect(workflow.nodes).to.deep.equal([initialTrigger, newTrigger]);
53
+ });
54
+ it('should add actions to the workflow', () => {
55
+ const trigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
56
+ trigger.setChainId(CHAINS.ETHEREUM);
57
+ trigger.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
58
+ trigger.setPosition(0, 0);
59
+ const action1 = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
60
+ action1.setChainId(CHAINS.ETHEREUM);
61
+ action1.setParams("value", 1000);
62
+ action1.setParams("to", "0xe1432599B51d9BE1b5A27E2A2FB8e5dF684749C6");
63
+ action1.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
64
+ action1.setPosition(1, 0);
65
+ const action2 = new Action(ACTIONS.NOTIFICATIONS.SLACK.SEND_MESSAGE);
66
+ action2.setParams("webhook", "https://webhook.url");
67
+ action2.setParams("message", "This is a test message");
68
+ action2.setPosition(2, 0);
69
+ const workflow = new Workflow("Test Workflow", [trigger]);
70
+ workflow.addNode(action1);
71
+ workflow.addNode(action2);
72
+ expect(workflow.nodes).to.deep.equal([trigger, action1, action2]);
73
+ });
74
+ it('should update an edge in the workflow', () => {
75
+ const trigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
76
+ trigger.setChainId(CHAINS.ETHEREUM);
77
+ trigger.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
78
+ trigger.setPosition(0, 0);
79
+ const action = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
80
+ action.setChainId(CHAINS.ETHEREUM);
81
+ action.setParams("value", 1000);
82
+ action.setParams("to", "0xe1432599B51d9BE1b5A27E2A2FB8e5dF684749C6");
83
+ action.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
84
+ action.setPosition(1, 0);
85
+ const edge = new Edge({
86
+ id: 'e-1',
87
+ source: trigger,
88
+ target: action,
89
+ });
90
+ const workflow = new Workflow("Test Workflow", [trigger, action], [edge]);
91
+ const newEdge = new Edge({
92
+ id: 'e-1',
93
+ source: action,
94
+ target: trigger,
95
+ });
96
+ workflow.updateEdge('e-1', newEdge);
97
+ const updatedEdge = workflow.edges.find(e => e.id === 'e-1');
98
+ expect(updatedEdge).to.deep.equal(newEdge);
99
+ });
100
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -3,6 +3,7 @@ export interface Token {
3
3
  name: string;
4
4
  symbol: string;
5
5
  decimals: number;
6
+ image: string | null;
6
7
  }
7
8
  export interface Tokens {
8
9
  [key: number]: Token[];
@@ -11,6 +12,7 @@ export declare const TOKENS: Tokens;
11
12
  export interface NFT {
12
13
  contractAddress: string;
13
14
  name: string;
15
+ image: string | null;
14
16
  }
15
17
  export interface NFTs {
16
18
  [key: number]: NFT[];
@@ -1,5 +1,5 @@
1
1
  import { Parameter } from './Parameter.js';
2
- import { Node, ParentInfo, Position } from './Node.js';
2
+ import { Node, ParentInfo, Position, NodeState } from './Node.js';
3
3
  export declare class Action extends Node {
4
4
  constructor(action: {
5
5
  blockId: number;
@@ -10,6 +10,7 @@ export declare class Action extends Node {
10
10
  ref?: string;
11
11
  position?: Position;
12
12
  parentInfo?: ParentInfo;
13
+ state?: NodeState;
13
14
  });
14
15
  getStaticParameters(): null;
15
16
  static fromJSON(json: {
@@ -13,5 +13,5 @@ export declare class Edge {
13
13
  };
14
14
  static fromJSON(json: {
15
15
  [key: string]: any;
16
- }): Edge;
16
+ }, nodes: Node[]): Edge;
17
17
  }
@@ -8,6 +8,7 @@ export interface ParentInfo {
8
8
  description: string;
9
9
  image: string;
10
10
  }
11
+ export type NodeState = 'inactive' | 'active' | 'failed' | 'completed';
11
12
  export declare abstract class Node {
12
13
  id: string | null;
13
14
  blockId: number;
@@ -24,6 +25,7 @@ export declare abstract class Node {
24
25
  class: string;
25
26
  image: string;
26
27
  parentInfo?: ParentInfo;
28
+ state: NodeState;
27
29
  constructor(node: {
28
30
  blockId: number;
29
31
  name: string;
@@ -34,6 +36,7 @@ export declare abstract class Node {
34
36
  class: string;
35
37
  image: string;
36
38
  parentInfo?: ParentInfo;
39
+ state?: NodeState;
37
40
  });
38
41
  setId(id: string): void;
39
42
  setChainId(value: number): void;
@@ -42,6 +45,7 @@ export declare abstract class Node {
42
45
  setPosition(x: number, y: number): void;
43
46
  getRef(): string;
44
47
  getParentInfo(): ParentInfo | undefined;
48
+ getState(): NodeState;
45
49
  protected setParameter(key: string, value: any): void;
46
50
  getParameter(key: string): any;
47
51
  getParameters(): {
@@ -1,4 +1,4 @@
1
- import { Node, ParentInfo, Position } from './Node.js';
1
+ import { Node, ParentInfo, Position, NodeState } from './Node.js';
2
2
  import { Parameter } from './Parameter.js';
3
3
  export declare class Trigger extends Node {
4
4
  type: number;
@@ -12,6 +12,7 @@ export declare class Trigger extends Node {
12
12
  ref?: string;
13
13
  position?: Position;
14
14
  parentInfo?: ParentInfo;
15
+ state?: NodeState;
15
16
  });
16
17
  private notAPollingTrigger;
17
18
  setCondition(value: string): void;
@@ -1,19 +1,24 @@
1
1
  import { Node } from './Node.js';
2
2
  import { Edge } from './Edge.js';
3
+ export type WorkflowState = 'inactive' | 'active' | 'failed' | 'completed';
3
4
  export declare class Workflow {
4
5
  id: string | null;
5
6
  name: string;
6
7
  nodes: Node[];
7
8
  edges: Edge[];
9
+ state: WorkflowState;
8
10
  constructor(name?: string, nodes?: Node[], edges?: Edge[]);
9
11
  setName(name: string): void;
10
12
  addNode(node: Node): void;
11
13
  addNodes(nodes: Node[]): void;
12
14
  addEdge(edge: Edge): void;
15
+ updateEdge(edgeId: string, newEdge: Edge): void;
13
16
  addEdges(edges: Edge[]): void;
17
+ getState(): WorkflowState;
14
18
  toJSON(): {
15
19
  id: string | null;
16
20
  name: string;
21
+ state: WorkflowState;
17
22
  nodes: {
18
23
  [key: string]: any;
19
24
  }[];
@@ -23,10 +28,7 @@ export declare class Workflow {
23
28
  };
24
29
  create(): Promise<{
25
30
  success: boolean;
26
- error?: undefined;
27
- } | {
28
- success: boolean;
29
- error: any;
31
+ error?: string;
30
32
  }>;
31
33
  update(): Promise<{
32
34
  success: boolean;
@@ -35,9 +37,6 @@ export declare class Workflow {
35
37
  load(workflowId: string): Promise<Workflow>;
36
38
  run(): Promise<{
37
39
  success: boolean;
38
- error?: undefined;
39
- } | {
40
- success: boolean;
41
- error: any;
40
+ error?: string;
42
41
  }>;
43
42
  }
@@ -9,6 +9,7 @@ declare class ApiServices {
9
9
  token: any;
10
10
  }>;
11
11
  verifyToken(token: string): Promise<any>;
12
+ getWorkflowsOfUser(): Promise<any>;
12
13
  }
13
14
  export declare const apiServices: ApiServices;
14
15
  export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -13,52 +13,50 @@ const main = async () => {
13
13
 
14
14
  const slackAction = new Action(ACTIONS.NOTIFICATIONS.SLACK.SEND_MESSAGE);
15
15
  slackAction.setParams("webhook", "https://hooks.slack.com/services/REPLACE_WITH_YOUR_DATA");
16
- slackAction.setParams("message", "Notification from the SDK");
16
+ slackAction.setParams("message", "Notification from the SDK - testing the state");
17
17
  slackAction.setPosition(0, -10);
18
18
 
19
- const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
19
+ /*const transferAction = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
20
20
  transferAction.setChainId(CHAINS.ETHEREUM);
21
21
  transferAction.setParams("value", 1000);
22
22
  transferAction.setParams("to", "0xe1432599B51d9BE1b5A27E2A2FB8e5dF684749C6");
23
- transferAction.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
23
+ transferAction.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);*/
24
24
 
25
- const workflow = new Workflow("test from SDK", [trigger, slackAction, transferAction]);
25
+ const workflow = new Workflow("test from SDK", [trigger, slackAction]);
26
26
 
27
27
  const edge = new Edge({
28
28
  source: trigger,
29
29
  target: slackAction,
30
30
  });
31
31
 
32
- const edge2 = new Edge({
33
- source: slackAction,
34
- target: transferAction,
35
- });
36
-
37
32
  workflow.addEdge(edge);
38
- workflow.addEdge(edge2);
39
33
 
40
34
  console.log(JSON.stringify(workflow.toJSON()))
41
35
 
42
36
  const creationResult = await workflow.create();
43
-
37
+ console.log(workflow.getState());
38
+
44
39
  if (!creationResult.success) {
45
40
  throw new Error("An error occurred when publishing the workflow")
46
41
  }
47
42
 
48
43
  console.log(workflow.id);
49
44
 
50
- /*const runResult = await workflow.run();
45
+ const runResult = await workflow.run();
46
+ console.log(workflow.getState());
51
47
 
52
48
  if (!runResult.success) {
53
49
  throw new Error("An error occurred when running the workflow")
54
50
  }
55
51
 
56
- console.log(`Workflow ${workflow.id} is running`);*/
52
+ console.log(`Workflow ${workflow.id} is running`);
53
+ console.log(workflow.getState());
57
54
 
58
55
  workflow.setName("ABC");
59
56
 
60
57
  const patchResult = await workflow.update();
61
58
  console.log(patchResult);
59
+ console.log(workflow.getState());
62
60
  }
63
61
 
64
62
  main();
@@ -3,8 +3,11 @@ import { ACTIONS, Action, TRIGGERS, Trigger, Workflow, CHAINS, getToken, Edge, a
3
3
  const main = async () => {
4
4
 
5
5
  apiServices.setAuth("eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIweDdjRUI4ZDgxNDdBYWE5ZEI4MUFjQkRGRTVjMzA1MERGQ2ZGMTg1MzciLCJzdWIiOiIweDg3RkU4YjRmMkZlODM3MGY2Y0M5YTk2MzQ0MmYwN0IwMmY0OTA5QTciLCJhdWQiOiJvdG9tYXRvLXRlc3QubmV0bGlmeS5hcHAiLCJleHAiOjE3MjMzODMxOTksIm5iZiI6MTcyMDc4OTM5OSwiaWF0IjoxNzIwNzkxMTk5LCJqdGkiOiIweDY4ZDkxOWEyMGZiYjIyNDUwZDZmOTFjMzM2ZTBmYjBjMmYyYTc3MmU3Zjg4NWU1ZjRmNzg1NTM2ZGIyYTY5YTAiLCJjdHgiOnt9fQ.MHgyOTM1NTM3MWYwOWM1YzllNWE3YjI4MjVkZTNjMDljZTkwMTQ3OTQwZmU1ZWRlMjM5YTk0MmFjYTQ5YTcwZWI0MGJlNmJiZDk2MDA4ZTIxMzJmNGM3ZTVlZGIzZDZiZjYyMDE4Mzc1MzUwMTRmNTc0ODM0ZDk4YWU3NDQwNDQzOTFi");
6
- const workflow = await new Workflow().load("2772afe3-17b8-4e98-bdae-669adca1956d");
7
- console.log(workflow)
6
+ const workflows = await apiServices.getWorkflowsOfUser();
7
+ // console.log(workflows);
8
+ // const workflow = await new Workflow().load(workflows[12].id);
9
+ const workflow = await new Workflow().load("815666d5-4232-4728-953a-abde4d85c8fd");
10
+ console.log(JSON.stringify(workflow));
8
11
  }
9
12
 
10
13
  main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "otomato-sdk",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "description": "An SDK for building and managing automations on Otomato",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/types/src/index.d.ts",
@@ -1,11 +1,11 @@
1
1
  import { Parameter } from './Parameter.js';
2
- import { Node, ParentInfo, Position } from './Node.js';
2
+ import { Node, ParentInfo, Position, NodeState } from './Node.js';
3
3
  import { ACTIONS } from '../constants/Blocks.js';
4
4
  import { ethers } from 'ethers';
5
5
  import { typeIsNumber } from '../utils/typeValidator.js';
6
6
 
7
7
  export class Action extends Node {
8
- constructor(action: { blockId: number; name: string; description: string; parameters: Parameter[], image: string, ref?: string, position?: Position, parentInfo?: ParentInfo }) {
8
+ constructor(action: { blockId: number; name: string; description: string; parameters: Parameter[], image: string, ref?: string, position?: Position, parentInfo?: ParentInfo, state?: NodeState }) {
9
9
  super({ ...action, class: 'action' });
10
10
  }
11
11
 
@@ -20,7 +20,8 @@ export class Action extends Node {
20
20
  ...enriched.block,
21
21
  ref: json.ref,
22
22
  position: json.position,
23
- parentInfo: enriched.parentInfo
23
+ parentInfo: enriched.parentInfo,
24
+ state: json.state
24
25
  });
25
26
 
26
27
  for (const [key, value] of Object.entries(json.parameters)) {
@@ -30,10 +30,16 @@ export class Edge {
30
30
  };
31
31
  }
32
32
 
33
- static fromJSON(json: { [key: string]: any }): Edge {
33
+ static fromJSON(json: { [key: string]: any }, nodes: Node[]): Edge {
34
+ const source = nodes.find(n => n.getRef() === json.source);
35
+ const target = nodes.find(n => n.getRef() === json.target);
36
+
37
+ if (!source || !target)
38
+ throw new Error("Edge refer to non existing node");
39
+
34
40
  return new Edge({
35
- source: json.source,
36
- target: json.target,
41
+ source,
42
+ target
37
43
  });
38
44
  }
39
45
  }
@@ -1,8 +1,6 @@
1
1
  import { Parameter } from './Parameter.js';
2
2
  import { validateType } from '../utils/typeValidator.js';
3
3
  import { ACTIONS, TRIGGERS } from '../constants/Blocks.js';
4
- import { Trigger } from './Trigger.js';
5
- import { Action } from './Action.js';
6
4
 
7
5
  export interface Position {
8
6
  x: number;
@@ -15,6 +13,8 @@ export interface ParentInfo {
15
13
  image: string;
16
14
  }
17
15
 
16
+ export type NodeState = 'inactive' | 'active' | 'failed' | 'completed';
17
+
18
18
  let nodeCounter = 0;
19
19
  const generatedRefs = new Set<string>();
20
20
 
@@ -30,8 +30,9 @@ export abstract class Node {
30
30
  class: string;
31
31
  image: string;
32
32
  parentInfo?: ParentInfo;
33
+ state: NodeState;
33
34
 
34
- constructor(node: { blockId: number; name: string; description: string; parameters: Parameter[], ref?: string, position?: Position, class: string; image: string; parentInfo?: ParentInfo }) {
35
+ constructor(node: { blockId: number; name: string; description: string; parameters: Parameter[], ref?: string, position?: Position, class: string; image: string; parentInfo?: ParentInfo, state?: NodeState }) {
35
36
  this.id = null;
36
37
  this.blockId = node.blockId;
37
38
  this.name = node.name;
@@ -41,6 +42,7 @@ export abstract class Node {
41
42
  this.keyMap = {};
42
43
  this.class = node.class;
43
44
  this.parentInfo = node.parentInfo;
45
+ this.state = node.state || 'inactive';
44
46
 
45
47
  if (node.ref) {
46
48
  this.ref = node.ref;
@@ -92,6 +94,10 @@ export abstract class Node {
92
94
  return this.parentInfo;
93
95
  }
94
96
 
97
+ getState(): NodeState {
98
+ return this.state;
99
+ }
100
+
95
101
  protected setParameter(key: string, value: any): void {
96
102
  if (key in this.parameters) {
97
103
  const param = this.parameters[key];
@@ -154,6 +160,7 @@ export abstract class Node {
154
160
  ref: this.ref,
155
161
  blockId: this.blockId,
156
162
  type: this.class,
163
+ state: this.state,
157
164
  parameters: {
158
165
  ...this.getParameters(),
159
166
  ...staticParameters,
@@ -183,5 +190,4 @@ export abstract class Node {
183
190
  throw new Error(`Unsupported type: ${json.type}`);
184
191
  }
185
192
  }
186
-
187
193
  }
@@ -1,4 +1,4 @@
1
- import { Node, ParentInfo, Position } from './Node.js';
1
+ import { Node, ParentInfo, Position, NodeState } from './Node.js';
2
2
  import { Parameter } from './Parameter.js';
3
3
  import { TRIGGERS } from '../constants/Blocks.js';
4
4
  import { ethers } from 'ethers';
@@ -7,7 +7,7 @@ import { typeIsNumber } from '../utils/typeValidator.js';
7
7
  export class Trigger extends Node {
8
8
  type: number;
9
9
 
10
- constructor(trigger: { blockId: number; name: string; description: string; type: number; parameters: Parameter[], image: string, ref?: string, position?: Position, parentInfo?: ParentInfo }) {
10
+ constructor(trigger: { blockId: number; name: string; description: string; type: number; parameters: Parameter[], image: string, ref?: string, position?: Position, parentInfo?: ParentInfo, state?: NodeState }) {
11
11
  super({ ...trigger, class: 'trigger' });
12
12
  this.type = trigger.type;
13
13
  }
@@ -44,7 +44,8 @@ export class Trigger extends Node {
44
44
  ...enriched.block,
45
45
  ref: json.ref,
46
46
  position: json.position,
47
- parentInfo: enriched.parentInfo
47
+ parentInfo: enriched.parentInfo,
48
+ state: json.state
48
49
  });
49
50
 
50
51
  for (const [key, value] of Object.entries(json.parameters)) {
@@ -2,16 +2,20 @@ import { Node } from './Node.js';
2
2
  import { Edge } from './Edge.js';
3
3
  import { apiServices } from '../services/ApiService.js';
4
4
 
5
+ export type WorkflowState = 'inactive' | 'active' | 'failed' | 'completed';
6
+
5
7
  export class Workflow {
6
8
  id: string | null = null;
7
9
  name: string;
8
10
  nodes: Node[];
9
11
  edges: Edge[];
12
+ state: WorkflowState;
10
13
 
11
14
  constructor(name: string = '', nodes: Node[] = [], edges: Edge[] = []) {
12
15
  this.name = name;
13
16
  this.nodes = nodes;
14
17
  this.edges = edges;
18
+ this.state = 'inactive';
15
19
  }
16
20
 
17
21
  setName(name: string): void {
@@ -30,20 +34,35 @@ export class Workflow {
30
34
  this.edges.push(edge);
31
35
  }
32
36
 
37
+ updateEdge(edgeId: string, newEdge: Edge): void {
38
+ const edgeToUpdate = this.edges.find(e => e.id === edgeId);
39
+ if (edgeToUpdate) {
40
+ edgeToUpdate.source = newEdge.source;
41
+ edgeToUpdate.target = newEdge.target;
42
+ } else {
43
+ throw new Error(`Edge with id ${edgeId} not found`);
44
+ }
45
+ }
46
+
33
47
  addEdges(edges: Edge[]): void {
34
48
  this.edges.push(...edges);
35
49
  }
36
50
 
51
+ getState(): WorkflowState {
52
+ return this.state;
53
+ }
54
+
37
55
  toJSON() {
38
56
  return {
39
57
  id: this.id,
40
58
  name: this.name,
59
+ state: this.state,
41
60
  nodes: this.nodes.map(node => node.toJSON()),
42
61
  edges: this.edges.map(edge => edge.toJSON()),
43
62
  };
44
63
  }
45
64
 
46
- async create() {
65
+ async create(): Promise<{ success: boolean; error?: string }> {
47
66
  try {
48
67
  const response = await apiServices.post('/workflows', this.toJSON());
49
68
 
@@ -70,7 +89,7 @@ export class Workflow {
70
89
  async update(): Promise<{ success: boolean; error?: string }> {
71
90
  try {
72
91
  const response = await apiServices.patch(`/workflows/${this.id}`, this.toJSON());
73
-
92
+
74
93
  if (response.status === 200) {
75
94
  // Assign IDs to the nodes based on the response
76
95
  response.data.nodes.forEach((nodeResponse: any) => {
@@ -79,7 +98,7 @@ export class Workflow {
79
98
  node.setId(nodeResponse.id);
80
99
  }
81
100
  });
82
-
101
+
83
102
  return { success: true };
84
103
  } else {
85
104
  return { success: false, error: response.data?.error || 'Unknown error' };
@@ -93,20 +112,22 @@ export class Workflow {
93
112
  const response = await apiServices.get(`/workflows/${workflowId}`);
94
113
  this.id = response.id;
95
114
  this.name = response.name;
115
+ this.state = response.state as WorkflowState;
96
116
  this.nodes = await Promise.all(response.nodes.map(async (nodeData: any) => await Node.fromJSON(nodeData)));
97
- this.edges = response.edges.map((edgeData: any) => Edge.fromJSON(edgeData));
117
+ this.edges = response.edges.map((edgeData: any) => Edge.fromJSON(edgeData, this.nodes));
98
118
  return this;
99
- }
119
+ }
100
120
 
101
- async run() {
121
+ async run(): Promise<{ success: boolean; error?: string }> {
102
122
  if (!this.id) {
103
123
  throw new Error('The workflow needs to be published first');
104
124
  }
105
-
125
+
106
126
  try {
107
127
  const response = await apiServices.post(`/workflows/${this.id}/run`, this.toJSON());
108
-
128
+
109
129
  if (response.status === 204) {
130
+ this.state = 'active';
110
131
  return { success: true };
111
132
  } else {
112
133
  return { success: false, error: response.data?.error || 'Unknown error' };
@@ -58,6 +58,12 @@ class ApiServices {
58
58
  const response = await axiosInstance.post('/auth/verify-token', { token }, { headers });
59
59
  return response.data;
60
60
  }
61
+
62
+ async getWorkflowsOfUser() {
63
+ const headers = this.auth ? { 'Authorization': this.auth } : {};
64
+ const response = await axiosInstance.get('/workflows', { headers });
65
+ return response.data;
66
+ }
61
67
  }
62
68
 
63
69
  export const apiServices = new ApiServices();
@@ -42,6 +42,7 @@ describe('Action Class', () => {
42
42
  ref: transferAction.getRef(),
43
43
  type: 'action',
44
44
  id: null,
45
+ state: 'inactive',
45
46
  parameters: {
46
47
  chainId: CHAINS.ETHEREUM,
47
48
  abi: {
@@ -101,6 +102,7 @@ describe('Action Class', () => {
101
102
  "ref": "n-2",
102
103
  "blockId": 100002,
103
104
  "type": "action",
105
+ "state": "inactive",
104
106
  "position": {
105
107
  "x": 0,
106
108
  "y": -10
@@ -128,6 +130,7 @@ describe('Action Class', () => {
128
130
  "ref": "n-3",
129
131
  "blockId": 100004,
130
132
  "type": "action",
133
+ "state": "inactive",
131
134
  "parameters": {
132
135
  "abi": {
133
136
  "parameters": {
package/test/node.spec.ts CHANGED
@@ -81,6 +81,7 @@ describe('Node Class', () => {
81
81
  expect(json).to.deep.equal({
82
82
  blockId: 5,
83
83
  id: null,
84
+ state: 'inactive',
84
85
  ref: node.getRef(),
85
86
  type: 'action',
86
87
  parameters: {
@@ -108,6 +109,7 @@ describe('Node Class', () => {
108
109
  type: 'action',
109
110
  blockId: 6,
110
111
  id: null,
112
+ state: 'inactive',
111
113
  ref: node.getRef(),
112
114
  parameters: {
113
115
  chainId: 1,
@@ -43,6 +43,7 @@ describe('Trigger Class', () => {
43
43
  ref: transferTrigger.getRef(),
44
44
  id: null,
45
45
  type: 'trigger',
46
+ state: "inactive",
46
47
  parameters: {
47
48
  chainId: CHAINS.ETHEREUM,
48
49
  abi: {
@@ -97,6 +98,7 @@ describe('Trigger Class', () => {
97
98
  "ref": "n-1",
98
99
  "blockId": 10,
99
100
  "type": "trigger",
101
+ "state": "inactive",
100
102
  "position": {
101
103
  "x": 0,
102
104
  "y": 0
@@ -131,6 +133,7 @@ describe('Trigger Class', () => {
131
133
  "ref": "n-1",
132
134
  "blockId": 1,
133
135
  "type": "trigger",
136
+ "state": "inactive",
134
137
  "parameters": {
135
138
  "chainId": 1,
136
139
  "abi": {
@@ -2,7 +2,7 @@ import { expect } from 'chai';
2
2
  import { Workflow } from '../src/models/Workflow.js';
3
3
  import { Trigger } from '../src/models/Trigger.js';
4
4
  import { Action } from '../src/models/Action.js';
5
- import { TRIGGERS, ACTIONS, getTokenFromSymbol, CHAINS } from '../src/index.js';
5
+ import { TRIGGERS, ACTIONS, getTokenFromSymbol, CHAINS, Edge } from '../src/index.js';
6
6
 
7
7
  describe('Workflow Class', () => {
8
8
  it('should create a workflow with a trigger and actions', () => {
@@ -30,7 +30,8 @@ describe('Workflow Class', () => {
30
30
  name: "Test Workflow",
31
31
  id: null,
32
32
  nodes: [trigger.toJSON(), action1.toJSON(), action2.toJSON()],
33
- edges: []
33
+ edges: [],
34
+ state: 'inactive'
34
35
  });
35
36
  });
36
37
 
@@ -87,4 +88,38 @@ describe('Workflow Class', () => {
87
88
 
88
89
  expect(workflow.nodes).to.deep.equal([trigger, action1, action2]);
89
90
  });
91
+
92
+ it('should update an edge in the workflow', () => {
93
+ const trigger = new Trigger(TRIGGERS.TOKENS.ERC20.TRANSFER);
94
+ trigger.setChainId(CHAINS.ETHEREUM);
95
+ trigger.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
96
+ trigger.setPosition(0, 0);
97
+
98
+ const action = new Action(ACTIONS.TOKENS.ERC20.TRANSFER);
99
+ action.setChainId(CHAINS.ETHEREUM);
100
+ action.setParams("value", 1000);
101
+ action.setParams("to", "0xe1432599B51d9BE1b5A27E2A2FB8e5dF684749C6");
102
+ action.setContractAddress(getTokenFromSymbol(CHAINS.ETHEREUM, 'USDC').contractAddress);
103
+ action.setPosition(1, 0);
104
+
105
+ const edge = new Edge({
106
+ id: 'e-1',
107
+ source: trigger,
108
+ target: action,
109
+ });
110
+
111
+ const workflow = new Workflow("Test Workflow", [trigger, action], [edge]);
112
+
113
+ const newEdge = new Edge({
114
+ id: 'e-1',
115
+ source: action,
116
+ target: trigger,
117
+ });
118
+
119
+ workflow.updateEdge('e-1', newEdge);
120
+
121
+ const updatedEdge = workflow.edges.find(e => e.id === 'e-1');
122
+
123
+ expect(updatedEdge).to.deep.equal(newEdge);
124
+ });
90
125
  });