antelopeql 2.0.0-rc.0 → 2.0.0-rc.10

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/antelopeql.mjs CHANGED
@@ -12,8 +12,8 @@ import blockchain_query_field from "./blockchain_query_field.mjs";
12
12
  import build_graphql_fields_from_abis from "./build_graphql_fields_from_abis.mjs";
13
13
  import get_abis from "./get_abis.mjs";
14
14
  import actions from "./graphql_input_types/actions.mjs";
15
- import push_serialized_transaction from "./push_serialized_transaction.mjs";
16
- import push_transaction from "./push_transaction.mjs";
15
+ import send_serialized_transaction from "./send_serialized_transaction.mjs";
16
+ import send_transaction from "./send_transaction.mjs";
17
17
  import serialize_transaction from "./serialize_transaction.mjs";
18
18
 
19
19
  /**
@@ -22,7 +22,6 @@ import serialize_transaction from "./serialize_transaction.mjs";
22
22
  * @property {String} rpc_url Chain remote proceedure call (RPC) Uniform Resource Locator (URL).
23
23
  * @property {*} [variableValues] GraphQL variables.
24
24
  * @property {String} [operationName] GraphQL operation name (query resolution).
25
- * @property {Function} [fetch] Custom fetch implementation.
26
25
  * @property {Array<String>} [contracts] List of Antelope smart contracts.
27
26
  * @property {async Function} [signTransaction] A function to sign the Antelope transaction.
28
27
  * @property {Headers} [headers] Headers to pass to the network request.
@@ -39,30 +38,12 @@ import serialize_transaction from "./serialize_transaction.mjs";
39
38
  * AntelopeQL for interacting with Antelope based blockchains.
40
39
  * @param {AntelopeQLArgument} Argument
41
40
  * @returns {AntelopeQLResult}
42
- * @example
43
- * ```js
44
- * import AntelopeQL from 'antelopeql/antelopeql.mjs'
45
- * import fetch from 'node-fetch'
46
- *
47
- * const query = `{ eosio_token { accounts(arg: { scope: "relockeblock" }){ balance } } }`
48
- *
49
- * AntelopeQL({
50
- * query,
51
- * contracts: ["eosio.token"],
52
- * fetch,
53
- * rpc_url: "https://eos.relocke.io",
54
- * headers: { "content-type": "application/json" }
55
- * }).then(console.log);
56
- * ```
57
- * > Logged output was "data": {"eosio_token": {"accounts": [{"balance": "100.0211 EOS"}]}}}
58
41
  */
59
-
60
42
  export default async function AntelopeQL({
61
43
  query,
62
44
  variableValues,
63
45
  operationName,
64
46
  signTransaction,
65
- fetch,
66
47
  contracts = [],
67
48
  ABIs = [],
68
49
  rpc_url,
@@ -70,9 +51,7 @@ export default async function AntelopeQL({
70
51
  signal
71
52
  }) {
72
53
  try {
73
- if (!fetch && !(typeof window == "undefined")) fetch = window.fetch;
74
- if (!fetch && typeof window == "undefined")
75
- throw new GraphQLError("No fetch implementation provided");
54
+ if (!fetch) throw new GraphQLError("No fetch implementation provided");
76
55
 
77
56
  const fetchOptions = {};
78
57
  if (headers) fetchOptions.headers = headers;
@@ -96,19 +75,17 @@ export default async function AntelopeQL({
96
75
  const action_fields = actions(mutation_fields);
97
76
  mutations = new GraphQLObjectType({
98
77
  name: "Mutation",
99
- description: "Push transactions to the blockchain.",
100
78
  fields: {
101
- push_transaction: push_transaction(action_fields, ast_list),
79
+ send_transaction: send_transaction(action_fields, ast_list),
102
80
  serialize_transaction: serialize_transaction(action_fields, ast_list),
103
- push_serialized_transaction
81
+ send_serialized_transaction
104
82
  }
105
83
  });
106
84
  } else
107
85
  mutations = new GraphQLObjectType({
108
86
  name: "Mutation",
109
- description: "Push transactions to the blockchain.",
110
87
  fields: {
111
- push_serialized_transaction
88
+ send_serialized_transaction
112
89
  }
113
90
  });
114
91
 
@@ -23,8 +23,7 @@ const currency_balance = {
23
23
  },
24
24
  symbol: {
25
25
  description: "The crytpo currency token symbol.",
26
- type: new GraphQLNonNull(symbol_code_type),
27
- defaultValue: "EOS"
26
+ type: new GraphQLNonNull(symbol_code_type)
28
27
  }
29
28
  },
30
29
  async resolve(_, args, { network: { fetch, rpc_url, ...fetchOptions } }) {
@@ -5,7 +5,7 @@ const RAM_quote_type = new GraphQLObjectType({
5
5
  fields: () => ({
6
6
  quote: {
7
7
  type: GraphQLString,
8
- resolve: (EOS) => EOS
8
+ resolve: (SYS) => SYS
9
9
  }
10
10
  })
11
11
  });
@@ -1,11 +1,84 @@
1
- // const { required_keys, ...errors } = await fetch(
2
- // `${rpc_url}/v1/chain/get_required_keys`,
3
- // {
4
- // method: "POST",
5
- // ...fetchOptions,
6
- // body: JSON.stringify({
7
- // available_keys,
8
- // transaction
9
- // })
10
- // }
11
- // ).then((res) => res.json());
1
+ import {
2
+ GraphQLError,
3
+ GraphQLInputObjectType,
4
+ GraphQLList,
5
+ GraphQLString
6
+ } from "graphql";
7
+
8
+ import bytes_type from "../eosio_types/bytes_type.mjs";
9
+ import name_type from "../eosio_types/name_type.mjs";
10
+ import public_key_type from "../eosio_types/public_key_type.mjs";
11
+ import authorization_type from "../graphql_input_types/authorization.mjs";
12
+
13
+ const action_type = new GraphQLInputObjectType({
14
+ name: "required_keys_action",
15
+ fields: {
16
+ account: {
17
+ type: name_type,
18
+ description: "The smart contract name"
19
+ },
20
+ name: { type: name_type },
21
+ authorization: { type: new GraphQLList(authorization_type) },
22
+ data: { type: GraphQLString },
23
+ hex_data: { type: bytes_type }
24
+ }
25
+ });
26
+
27
+ const transaction_type = new GraphQLInputObjectType({
28
+ name: "required_keys_transaction",
29
+ fields: {
30
+ expiration: { type: GraphQLString },
31
+ ref_block_num: { type: GraphQLString },
32
+ ref_block_prefix: { type: GraphQLString },
33
+ max_net_usage_words: { type: GraphQLString },
34
+ max_cpu_usage_ms: { type: GraphQLString },
35
+ actions: { type: new GraphQLList(action_type) },
36
+ context_free_actions: { type: GraphQLString }
37
+ }
38
+ });
39
+
40
+ const get_required_keys = {
41
+ description: "Retrieve a table from the blockchain.",
42
+ type: new GraphQLList(public_key_type),
43
+ args: {
44
+ transaction: {
45
+ type: transaction_type
46
+ },
47
+ available_keys: {
48
+ type: new GraphQLList(public_key_type)
49
+ }
50
+ },
51
+ async resolve(
52
+ _,
53
+ { available_keys, transaction },
54
+ { network: { fetch, rpc_url } }
55
+ ) {
56
+ const uri = `${rpc_url}/v1/chain/get_required_keys`;
57
+
58
+ const { actions, ...txn } = transaction;
59
+
60
+ const data = await fetch(uri, {
61
+ method: "POST",
62
+ body: JSON.stringify({
63
+ available_keys: await Promise.all(available_keys),
64
+ transaction: {
65
+ ...txn,
66
+ actions: actions.map(({ data, ...object }) => ({
67
+ ...object,
68
+ ...(data ? { data: JSON.parse(data) } : {})
69
+ }))
70
+ }
71
+ })
72
+ });
73
+
74
+ const { required_keys, ...error } = await data.json();
75
+ if (error.error)
76
+ throw new GraphQLError(error.message, {
77
+ extensions: error.error
78
+ });
79
+
80
+ return required_keys;
81
+ }
82
+ };
83
+
84
+ export default get_required_keys;
@@ -0,0 +1,53 @@
1
+ import {
2
+ GraphQLError,
3
+ GraphQLNonNull,
4
+ GraphQLObjectType,
5
+ GraphQLString
6
+ } from "graphql";
7
+
8
+ import name_type from "../eosio_types/name_type.mjs";
9
+
10
+ const smart_contract_type = new GraphQLObjectType({
11
+ name: "smart_contract_type",
12
+ fields: () => ({
13
+ wasm: {
14
+ type: GraphQLString,
15
+ description: "base64 encoded contract WASM"
16
+ },
17
+ abi: {
18
+ description: "base64 encoded contract ABI",
19
+ type: GraphQLString
20
+ }
21
+ })
22
+ });
23
+
24
+ const get_smart_contract = {
25
+ description: "Retrieve a smart contract from the blockchain.",
26
+ type: smart_contract_type,
27
+ args: {
28
+ account_name: {
29
+ description: "The account holding the `smart contract`.",
30
+ type: new GraphQLNonNull(name_type)
31
+ }
32
+ },
33
+ async resolve(
34
+ _,
35
+ { account_name },
36
+ { network: { fetch, rpc_url, ...fetchOptions } }
37
+ ) {
38
+ const uri = `${rpc_url}/v1/chain/get_raw_code_and_abi`;
39
+ const data = await fetch(uri, {
40
+ method: "POST",
41
+ ...fetchOptions,
42
+ body: JSON.stringify({
43
+ account_name,
44
+ code_as_wasm: 1
45
+ })
46
+ }).then((req) => req.json());
47
+
48
+ if (data.error) throw new GraphQLError(data.message, { extensions: data });
49
+ return data;
50
+ }
51
+ };
52
+
53
+ export default get_smart_contract;
@@ -10,6 +10,8 @@ import get_currency_stats from "./blockchain/get_currency_stats.mjs";
10
10
  import get_info from "./blockchain/get_info.mjs";
11
11
  import get_producers from "./blockchain/get_producers.mjs";
12
12
  import get_ram_price from "./blockchain/get_ram_price.mjs";
13
+ import get_required_keys from "./blockchain/get_required_keys.mjs";
14
+ import get_smart_contract from "./blockchain/get_smart_contract.mjs";
13
15
  import get_table from "./blockchain/get_table_by_scope.mjs";
14
16
 
15
17
  const blockchain_query_field = {
@@ -23,20 +25,19 @@ const blockchain_query_field = {
23
25
  get_block,
24
26
  get_currency_balance,
25
27
  get_currency_stats,
28
+ get_required_keys,
29
+ get_smart_contract,
26
30
  get_info,
27
31
  get_producers,
28
- deserialize_action_data,
29
32
  get_table,
30
- get_ram_price
33
+ get_ram_price,
34
+ deserialize_action_data
31
35
  }
32
36
  }),
33
- resolve(_, __, { network: { fetch, rpc_url } }) {
34
- if (!fetch)
35
- throw new GraphQLError(
36
- "Fetch was not supplied to the `antelopeql_context`."
37
- );
37
+ resolve(_, __, { network: { rpc_url } }) {
38
38
  if (!rpc_url)
39
39
  throw new GraphQLError("No RPC url supplied to `antelopeql_context`");
40
+
40
41
  return {};
41
42
  }
42
43
  };
@@ -26,7 +26,7 @@ import {
26
26
  * ```js
27
27
  * import actions_type from 'antelopeql/graphql_input_types/actions.js'
28
28
  * import serialize_transaction from 'antelopeql/graphql_input_types/actions.js'
29
- * import push_transaction from 'antelopeql/push_transaction.js'
29
+ * import send_transaction from 'antelopeql/send_transaction.js'
30
30
  *
31
31
  * const network = { fetch, rpc_url: 'https://eos.relocke.io', headers: {}, signal }
32
32
  * const ABI_list = [{ account_name: 'eosio.token', abi: … }]
@@ -45,9 +45,9 @@ import {
45
45
  * const mutations = new GraphQLObjectType({
46
46
  * name: 'Mutation',
47
47
  * fields: {
48
- * push_transaction: push_transaction(action_fields, ast_list),
48
+ * send_transaction: send_transaction(action_fields, ast_list),
49
49
  * serialize_transaction: serialize_transaction(action_fields, ast_list),
50
- * push_serialized_transaction
50
+ * send_serialized_transaction
51
51
  * }
52
52
  * })
53
53
  *
@@ -69,15 +69,17 @@ export function eosio_abi_to_graphql_ast(abi) {
69
69
  const { types, variants } = abi;
70
70
 
71
71
  let structs = [
72
- ...variants.map(({ name, types }) => ({
73
- name,
74
- base: "",
75
- fields: types.map((item) => ({ name: item, type: item + "$@" })) // @ indiacted a variant type and binary extention.
76
- })),
72
+ ...(variants?.length
73
+ ? variants.map(({ name, types }) => ({
74
+ name,
75
+ base: "",
76
+ fields: types.map((item) => ({ name: item, type: item + "$@" })) // @ indiacted a variant type and binary extention.
77
+ }))
78
+ : []),
77
79
  ...abi.structs
78
80
  ];
79
81
 
80
- if (types.length)
82
+ if (types?.length)
81
83
  for (const { type: real_type, new_type_name } of types)
82
84
  structs = structs.map(({ fields, ...struct }) => ({
83
85
  ...struct,
@@ -1,11 +1,9 @@
1
+ import base58_to_binary from "base58-js/base58_to_binary.mjs";
2
+ import binary_to_base58 from "base58-js/binary_to_base58.mjs";
1
3
  import { GraphQLScalarType } from "graphql";
4
+ import ripemd160 from "ripemd160-js/ripemd160.mjs";
2
5
 
3
6
  const public_key_type = new GraphQLScalarType({
4
- description: `\`Public key type\`
5
- ---
6
-
7
- Public keys should begin with PUB_K1 (or EOS for legacy keys) and include base58 characters only.
8
- `,
9
7
  name: "public_key",
10
8
  async parseValue(public_key) {
11
9
  if (public_key == "") return "";
@@ -21,6 +19,22 @@ const public_key_type = new GraphQLScalarType({
21
19
  );
22
20
 
23
21
  return public_key;
22
+ },
23
+ async serialize(key) {
24
+ if (key.startsWith("EOS")) {
25
+ const public_key = base58_to_binary(key.replace(/^[A-Z]+/gmu, "")).slice(
26
+ 0,
27
+ -4
28
+ );
29
+
30
+ const hash = await ripemd160(Uint8Array.from([...public_key, 75, 49]));
31
+ const checksum = hash.slice(0, 4);
32
+ return (
33
+ "PUB_K1_" +
34
+ binary_to_base58(new Uint8Array([...public_key, ...checksum]))
35
+ );
36
+ }
37
+ return key;
24
38
  }
25
39
  });
26
40
 
@@ -3,15 +3,13 @@ import { GraphQLScalarType } from "graphql";
3
3
  const signature_type = new GraphQLScalarType({
4
4
  description: `\`Signature type\`
5
5
 
6
- EOS K1 signature supported.`,
6
+ Antelope based signature, K1, R1 WA.`,
7
7
  name: "signature",
8
8
  parseValue(signature) {
9
9
  if (signature == "") return "";
10
10
  if (typeof signature !== "string")
11
11
  throw new TypeError("Expected signature to be string");
12
12
 
13
- if (signature.slice(0, 7) != "SIG_K1_")
14
- throw new TypeError("Signature prefix is should be SIG_K1_.");
15
13
  return signature;
16
14
  }
17
15
  });
@@ -17,7 +17,6 @@ const configuration_default_value = {
17
17
  * @param {Number} expireSeconds Seconds past before transaction is no longer valid (TaPoS protection)
18
18
  * @param {Number} max_net_usage_words Maximum NET bandwidth usage a transaction can consume (0 there is no limit).
19
19
  * @param {Number} max_cpu_usage_ms Maximum NET bandwidth usage a transaction can consume (0 there is no limit).
20
- * @param {Number} delay_sec Number of seconds that the transaciton will be delayed by.
21
20
  */
22
21
  const configuration_type = new GraphQLInputObjectType({
23
22
  name: "configuration_type",
@@ -43,11 +42,6 @@ const configuration_type = new GraphQLInputObjectType({
43
42
  description: `Maximum CPU bandwidth usage a transaction can consume, \nwhen set to 0 there is no limit`,
44
43
  type: GraphQLInt,
45
44
  defaultValue: configuration_default_value.max_cpu_usage_ms
46
- },
47
- delay_sec: {
48
- type: GraphQLInt,
49
- description: "Number of seconds that the transaciton will be delayed by",
50
- defaultValue: configuration_default_value.delay_sec
51
45
  }
52
46
  })
53
47
  });
@@ -1,4 +1,77 @@
1
- import { GraphQLObjectType, GraphQLString } from "graphql";
1
+ import { GraphQLError, GraphQLList, GraphQLObjectType } from "graphql";
2
+ import sha256 from "universal-sha256-js/sha256.mjs";
3
+
4
+ import bytes_type from "../eosio_types/bytes_type.mjs";
5
+ import public_key_type from "../eosio_types/public_key_type.mjs";
6
+
7
+ export const packed_transaction_fields = {
8
+ chain_id: {
9
+ type: bytes_type,
10
+ description: "A unique ID that specifies which chain we are operating on."
11
+ },
12
+ transaction_header: {
13
+ type: bytes_type,
14
+ description: "Serialized transaction header."
15
+ },
16
+ transaction_body: {
17
+ type: bytes_type,
18
+ description: "Serialized transaction body _(bytecode instructions)_."
19
+ },
20
+ required_keys: {
21
+ type: new GraphQLList(public_key_type),
22
+ description: "List of public keys needed to authorize transaction",
23
+ async resolve({ available_keys, transaction }, args, { network }) {
24
+ if (available_keys?.length) {
25
+ const keys = await Promise.all(available_keys);
26
+
27
+ const req = await fetch(
28
+ network.rpc_url + "/v1/chain/get_required_keys",
29
+ {
30
+ method: "post",
31
+ body: JSON.stringify({
32
+ transaction: {
33
+ ...transaction,
34
+ // Transform the transaction.actions into appropriate form for get_required_keys.
35
+ actions: transaction.actions.map(({ hex_data, ...action }) => ({
36
+ ...action,
37
+ data: hex_data
38
+ }))
39
+ },
40
+ available_keys: keys
41
+ })
42
+ }
43
+ ).then((res) => res.json());
44
+
45
+ if (req.error)
46
+ throw new GraphQLError(req.message, { extensions: req.error });
47
+ return req.required_keys;
48
+ }
49
+ }
50
+ },
51
+ hash: {
52
+ type: bytes_type,
53
+ description: "Transaction hash to sign to authorize transaction",
54
+ async resolve({ chain_id, transaction_header, transaction_body }) {
55
+ const transaction_bytes =
56
+ chain_id +
57
+ transaction_header +
58
+ transaction_body +
59
+ "0000000000000000000000000000000000000000000000000000000000000000";
60
+
61
+ const hash_to_sign = await sha256(
62
+ Uint8Array.from(
63
+ transaction_bytes
64
+ .match(/[a-fA-F0-9]{2}/gmu)
65
+ .map((i) => Number(`0x${i}`))
66
+ )
67
+ );
68
+
69
+ return [...hash_to_sign]
70
+ .map((x) => Number(x).toString(16).padStart(2, "0"))
71
+ .join("");
72
+ }
73
+ }
74
+ };
2
75
 
3
76
  /**
4
77
  * The packed transaction type.
@@ -8,25 +81,12 @@ import { GraphQLObjectType, GraphQLString } from "graphql";
8
81
  * @prop {String} chain_id Hash representing the blockchain.
9
82
  * @prop {String} transaction_header Hex string representing the serialized transaction header.
10
83
  * @prop {String} transaction_body Hex string representing the serialized transaction body.
11
-
84
+ * @prop {String} transaction_body Hex string representing the serialized transaction body.
12
85
  */
13
86
  const packed_transaction_type = new GraphQLObjectType({
14
87
  name: "packed_transaction",
15
88
  description: "Packed transaction, chain ID and transaction header",
16
- fields: {
17
- chain_id: {
18
- type: GraphQLString,
19
- description: "A unique ID that Specifies which chain we are operating on."
20
- },
21
- transaction_header: {
22
- type: GraphQLString,
23
- description: "Serialized transaction header _(TaPoS protection)_."
24
- },
25
- transaction_body: {
26
- type: GraphQLString,
27
- description: "Serialized transaction body _(bytecode instructions)_."
28
- }
29
- }
89
+ fields: packed_transaction_fields
30
90
  });
31
91
 
32
92
  export default packed_transaction_type;
@@ -2,12 +2,11 @@ import serialize from "eosio-wasm-js/serialize.mjs";
2
2
  import serialize_transaction_header from "eosio-wasm-js/transaction_header.mjs";
3
3
  import { GraphQLError } from "graphql";
4
4
 
5
- const defeaul_config = {
5
+ const default_config = {
6
6
  blocksBehind: 3,
7
7
  expireSeconds: 30,
8
8
  max_net_usage_words: 0,
9
- max_cpu_usage_ms: 0,
10
- delay_sec: 0
9
+ max_cpu_usage_ms: 0
11
10
  };
12
11
 
13
12
  const validate_actions = () => {
@@ -48,8 +47,7 @@ async function get_transaction_body(actions, ast_list) {
48
47
  let _actions = [];
49
48
  let _context_free_actions = [];
50
49
 
51
- let transaction_extensions =
52
- "000000000000000000000000000000000000000000000000000000000000000000";
50
+ let transaction_extensions = "00";
53
51
 
54
52
  for (const action of actions_list_to_serialize) {
55
53
  const {
@@ -164,7 +162,7 @@ async function get_transaction_body(actions, ast_list) {
164
162
  * @returns {Object} Transaction object.
165
163
  */
166
164
  async function mutation_resolver(
167
- { actions, configuration = defeaul_config },
165
+ { actions, configuration = default_config },
168
166
  network,
169
167
  ast_list
170
168
  ) {
@@ -213,10 +211,10 @@ async function mutation_resolver(
213
211
  ref_block_prefix,
214
212
  max_net_usage_words: configuration.max_net_usage_words,
215
213
  max_cpu_usage_ms: configuration.max_cpu_usage_ms,
216
- delay_sec: configuration.delay_sec
214
+ delay_sec: 0
217
215
  };
218
216
 
219
- // Generates a transaction header for a EOS transaction.
217
+ // Generates a transaction header for a Antelope transaction.
220
218
  const transaction_header = serialize_transaction_header(txn_header);
221
219
  txn_header.expiration = timestamp;
222
220
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antelopeql",
3
- "version": "2.0.0-rc.0",
3
+ "version": "2.0.0-rc.10",
4
4
  "description": "A GraphQL implementation for interacting with Antelope based blockchains.",
5
5
  "repository": "github:pur3miish/antelopeql",
6
6
  "bugs": "https://github.com/pur3miish/antelopeql/issues",
@@ -11,6 +11,7 @@
11
11
  "eslint": "eslint .",
12
12
  "prettier": "prettier -c .",
13
13
  "prettier:readme": "prettier --write readme.md",
14
+ "server": "nodemon test/server.mjs",
14
15
  "types": "tsc -p jsconfig.json",
15
16
  "snapshot": "SAVE_SNAPSHOTS=1 coverage-node test/index.test.mjs",
16
17
  "coverage": "coverage-node test/index.test.mjs",
@@ -19,26 +20,27 @@
19
20
  "prepublishOnly": "npm test"
20
21
  },
21
22
  "engines": {
22
- "node": "^16.0.0 || >= 17.0.0 || >= 18.0.0"
23
+ "node": ">= 18.0.0"
23
24
  },
24
25
  "files": [
25
26
  "blockchain/*.mjs",
26
27
  "eosio_types/*.mjs",
27
28
  "graphql_input_types/*.mjs",
28
29
  "graphql_object_types/*.mjs",
30
+ "antelopeql.mjs",
29
31
  "blockchain_query_field.mjs",
30
32
  "build_graphql_fields_from_abis.mjs",
31
33
  "eosio_abi_to_graphql_ast.mjs",
32
34
  "eosio_types.mjs",
35
+ "get_abis.mjs",
33
36
  "mutation_resolver.mjs",
34
- "push_serialized_transaction.mjs",
35
- "push_transaction_rpc.mjs",
36
- "push_transaction.mjs",
37
37
  "query_resolver.mjs",
38
+ "send_serialized_transaction.mjs",
39
+ "send_transaction_rpc.mjs",
40
+ "send_transaction.mjs",
41
+ "serialize_abi.mjs",
38
42
  "serialize_transaction.mjs",
39
- "antelopeql.mjs",
40
- "types.mjs",
41
- "get_abis.mjs"
43
+ "types.mjs"
42
44
  ],
43
45
  "sideEffects": false,
44
46
  "exports": {
@@ -46,19 +48,20 @@
46
48
  "./eosio_types/*.mjs": "./eosio_types/*.mjs",
47
49
  "./graphql_input_types/*.mjs": "./graphql_input_types/*.mjs",
48
50
  "./graphql_object_types/*.mjs": "./graphql_object_types/*.mjs",
51
+ "./antelopeql.mjs": "./antelopeql.mjs",
49
52
  "./blockchain_query_field.mjs": "./blockchain_query_field.mjs",
50
53
  "./build_graphql_fields_from_abis.mjs": "./build_graphql_fields_from_abis.mjs",
51
54
  "./eosio_abi_to_graphql_ast.mjs": "./eosio_abi_to_graphql_ast.mjs",
52
55
  "./eosio_types.mjs": "./eosio_types.mjs",
56
+ "./get_abis.mjs": "./get_abis.mjs",
53
57
  "./mutation_resolver.mjs": "./mutation_resolver.mjs",
54
- "./push_serialized_transaction.mjs": "./push_serialized_transaction.mjs",
55
- "./push_transaction_rpc.mjs": "./push_transaction_rpc.mjs",
56
- "./push_transaction.mjs": "./push_transaction.mjs",
57
58
  "./query_resolver.mjs": "./query_resolver.mjs",
59
+ "./send_serialized_transaction.mjs": "./send_serialized_transaction.mjs",
60
+ "./send_transaction_rpc.mjs": "./send_transaction_rpc.mjs",
61
+ "./send_transaction.mjs": "./send_transaction.mjs",
62
+ "./serialize_abi.mjs": "./serialize_abi.mjs",
58
63
  "./serialize_transaction.mjs": "./serialize_transaction.mjs",
59
- "./antelopeql.mjs": "./antelopeql.mjs",
60
- "./types.mjs": "./types.mjs",
61
- "./get_abis.mjs": "./get_abis.mjs"
64
+ "./types.mjs": "./types.mjs"
62
65
  },
63
66
  "browserslist": [
64
67
  "> 0.5%, not OperaMini all, not IE > 0, not dead"
@@ -76,23 +79,20 @@
76
79
  ],
77
80
  "devDependencies": {
78
81
  "@types/node": "^18.13.0",
82
+ "antelope-ecc": "^2.0.0-rc.7",
79
83
  "coverage-node": "^8.0.0",
80
84
  "eslint": "^8.34.0",
81
85
  "eslint-plugin-simple-import-sort": "^10.0.0",
82
- "graphql": "^16.6.0",
83
- "node-fetch": "^3.3.0",
84
- "nodemon": "^2.0.20",
86
+ "graphql": "^16.8.0",
87
+ "nodemon": "^3.0.1",
85
88
  "prettier": "^2.8.4",
86
89
  "snapshot-assertion": "^5.0.0",
87
90
  "test-director": "^10.0.0",
88
91
  "typescript": "^4.9.5"
89
92
  },
90
- "peerDependencies": {
91
- "graphql": "^16.6.0"
92
- },
93
93
  "dependencies": {
94
94
  "base58-js": "^2.0.0",
95
- "eosio-wasm-js": "^4.1.0",
95
+ "eosio-wasm-js": "^4.1.1",
96
96
  "ripemd160-js": "*",
97
97
  "universal-sha256-js": "^2.0.0"
98
98
  }
package/readme.md CHANGED
@@ -31,42 +31,35 @@ See the examples folder on how to run AntelopeQL as a [Node.js](https://nodejs.o
31
31
  ### Query a blockchain account
32
32
 
33
33
  ```js
34
- import fetch from "node-fetch";
35
34
  import AntelopeQL from "antelopeql/antelopeql.mjs";
36
35
 
37
- const { data } = await AntelopeQL(
38
- {
39
- query: /*GraphQL*/ `{
40
- blockchain{
41
- get_account(account_name:"relockeblock") {
42
- core_liquid_balance
43
- ram_quota
44
- net_weight
45
- cpu_weight
46
- ram_usage
47
- permissions {
48
- linked_actions {
49
- account
50
- action
51
- }
52
- required_auth {
53
- keys {
54
- key
55
- weight
36
+ const { data } = await AntelopeQL({
37
+ query: /*GraphQL*/ `{
38
+ blockchain{
39
+ get_account(account_name:"relockeblock") {
40
+ core_liquid_balance
41
+ ram_quota
42
+ net_weight
43
+ cpu_weight
44
+ ram_usage
45
+ permissions {
46
+ linked_actions {
47
+ account
48
+ action
49
+ }
50
+ required_auth {
51
+ keys {
52
+ key
53
+ weight
54
+ }
55
+ threshold
56
56
  }
57
- threshold
58
57
  }
59
58
  }
60
59
  }
61
- }
62
- }`
63
- fetch,
64
- rpc_url: "https://jungle.relocke.io",
65
- headers: {
66
- "content-type": "application/json"
67
- }
68
- },
69
- );
60
+ }`,
61
+ rpc_url: "https://jungle.relocke.io"
62
+ });
70
63
 
71
64
  console.log(data);
72
65
  ```
@@ -76,13 +69,13 @@ console.log(data);
76
69
  ### Transfer EOS cryptocurrency
77
70
 
78
71
  ```js
79
- import fetch from "node-fetch";
80
72
  import AntelopeQL from "antelopeql/antelopeql.mjs";
73
+ import sign_txn from "antelopeql-ecc/sign_txn.mjs";
81
74
 
82
75
  const { data } = await AntelopeQL({
83
76
  query: /*GraphQL*/ `
84
- mutation{
85
- push_transaction(actions: [{
77
+ mutation {
78
+ send_transaction(actions: [{
86
79
  eosio_token:{
87
80
  transfer: {
88
81
  authorization:{
@@ -98,18 +91,14 @@ const { data } = await AntelopeQL({
98
91
  transaction_id
99
92
  block_num
100
93
  }
101
- }`,
102
- contracts: ["eosio.token"],
103
- signTransaction: async () => {
104
- const private_keys = [...] // your private keys
105
- const signatures = generate_signature_function(...privatekeys) // your antelope digital signature provider
106
- return signatures // signaures must return array
107
- }
108
- fetch,
109
- rpc_url: "https://eos.relocke.io", // eos blockchain.
110
- headers: {
111
- "content-type": "application/json"
112
- }
94
+ }`,
95
+ contracts: ["eosio.token", "eosio"], // List of smart contracts
96
+ signTransaction: async (hash) => {
97
+ const wif_private_key = "PVT_K1_…"; // your private key
98
+ const signature = await sign_txn({ hash, wif_private_key });
99
+ return [signature]; // signaures must return array
100
+ },
101
+ rpc_url: "https://eos.relocke.io" // eos blockchain url.
113
102
  });
114
103
 
115
104
  console.log(data);
@@ -134,24 +123,9 @@ console.log(data);
134
123
 
135
124
  Supported runtime environments:
136
125
 
137
- - [Node.js](https://nodejs.org) versions `>=16.0.0`.
126
+ - [Node.js](https://nodejs.org) versions `>=18.0.0`.
138
127
  - Browsers matching the [Browserslist](https://browsersl.ist) query [`> 0.5%, not OperaMini all, not dead`](https://browsersl.ist/?q=%3E+0.5%25%2C+not+OperaMini+all%2C+not+dead).
139
- - [Deno](https://deno.land) version `>=1.30.0`.
140
128
 
141
129
  ## Exports
142
130
 
143
131
  The [npm](https://npmjs.com) package [`AntelopeQL`](https://npm.im/antelopeql) features [optimal JavaScript module design](https://jaydenseric.com/blog/optimal-javascript-module-design). It doesn’t have a main index module, so use deep imports from the ECMAScript modules that are exported via the [`package.json`](./package.json) field [`exports`](https://nodejs.org/api/packages.html#exports):
144
-
145
- - [`antelopeql.mjs`](./antelopeql.mjs)
146
- - [`blockchain_query_field.mjs`](blockchain_query_field.mjs)
147
- - [`build_graphql_fields_from_abis.mjs`](build_graphql_fields_from_abis.mjs)
148
- - [`eosio_abi_to_graphql_ast.mjs`](eosio_abi_to_graphql_ast.mjs)
149
- - [`eosio_types.mjs`](eosio_types.mjs)
150
- - [`mutation_resolver.mjs`](mutation_resolver.mjs)
151
- - [`push_serialized_transaction.mjs`](push_serialized_transaction.mjs)
152
- - [`push_transaction_rpc.mjs`](push_transaction_rpc.mjs)
153
- - [`push_transaction.mjs`](push_transaction.mjs)
154
- - [`query_resolver.mjs`](query_resolver.mjs)
155
- - [`serialize_transaction.mjs`](serialize_transaction.mjs)
156
- - [`antelopeql.mjs`](antelopeql.mjs)
157
- - [`types.mjs`](types.mjs)
@@ -3,13 +3,13 @@ import { GraphQLList, GraphQLNonNull } from "graphql";
3
3
  import bytes_type from "./eosio_types/bytes_type.mjs";
4
4
  import signature_type from "./eosio_types/signature_type.mjs";
5
5
  import transaction_receipt from "./graphql_object_types/transaction_receipt.mjs";
6
- import push_transaction_rpc from "./push_transaction_rpc.mjs";
6
+ import send_transaction_rpc from "./send_transaction_rpc.mjs";
7
7
 
8
8
  /**
9
9
  * Push transaction type.
10
10
  */
11
- const push_serialized_transaction = {
12
- description: "Pushes a serialized transaction to the blockchain.",
11
+ const send_serialized_transaction = {
12
+ description: "Sends a serialized transaction to the blockchain.",
13
13
  type: new GraphQLNonNull(transaction_receipt),
14
14
  args: {
15
15
  transaction_header: { type: new GraphQLNonNull(bytes_type) },
@@ -17,8 +17,8 @@ const push_serialized_transaction = {
17
17
  signaures: { type: new GraphQLNonNull(new GraphQLList(signature_type)) }
18
18
  },
19
19
  resolve(_, args, ctx) {
20
- return push_transaction_rpc(args, ctx.network);
20
+ return send_transaction_rpc(args, ctx.network);
21
21
  }
22
22
  };
23
23
 
24
- export default push_serialized_transaction;
24
+ export default send_serialized_transaction;
@@ -4,9 +4,9 @@ import sha256 from "universal-sha256-js/sha256.mjs";
4
4
  import configuration_type from "./graphql_input_types/configuration.mjs";
5
5
  import transaction_receipt from "./graphql_object_types/transaction_receipt.mjs";
6
6
  import mutation_resolver from "./mutation_resolver.mjs";
7
- import push_transaction_rpc from "./push_transaction_rpc.mjs";
7
+ import send_transaction_rpc from "./send_transaction_rpc.mjs";
8
8
 
9
- const push_transaction = (actions, ast_list) => ({
9
+ const send_transaction = (actions, ast_list) => ({
10
10
  description:
11
11
  "Serialize a list of actions and push them to the blockchain in one step, requires private keys to be supplied to AntelopeQL.",
12
12
  type: new GraphQLNonNull(transaction_receipt),
@@ -22,7 +22,11 @@ const push_transaction = (actions, ast_list) => ({
22
22
  const { chain_id, transaction_header, transaction_body, transaction } =
23
23
  await mutation_resolver(args, network, ast_list);
24
24
 
25
- const transaction_bytes = chain_id + transaction_header + transaction_body;
25
+ const transaction_bytes =
26
+ chain_id +
27
+ transaction_header +
28
+ transaction_body +
29
+ "0000000000000000000000000000000000000000000000000000000000000000";
26
30
 
27
31
  const hash_to_sign = await sha256(
28
32
  Uint8Array.from(
@@ -41,11 +45,11 @@ const push_transaction = (actions, ast_list) => ({
41
45
  transaction
42
46
  });
43
47
 
44
- return push_transaction_rpc(
48
+ return send_transaction_rpc(
45
49
  { transaction_body, transaction_header, signatures },
46
50
  network
47
51
  );
48
52
  }
49
53
  });
50
54
 
51
- export default push_transaction;
55
+ export default send_transaction;
@@ -1,7 +1,7 @@
1
1
  import { GraphQLError } from "graphql";
2
2
 
3
3
  /**
4
- * Pushes a serialized transaction to the blockchain.
4
+ * Send a serialized transaction to the blockchain.
5
5
  * @param {Object} root Argument
6
6
  * @param {String} root.transaction_header Serialized transaction header.
7
7
  * @param {String} root.transaction_body Serialized transaction body.
@@ -12,15 +12,13 @@ import { GraphQLError } from "graphql";
12
12
  * @param {Object} network.headers transaction headers.
13
13
  *
14
14
  */
15
- export default async function push_transaction_rpc(
15
+ export default async function send_transaction_rpc(
16
16
  { transaction_header, transaction_body, signatures },
17
17
  network
18
18
  ) {
19
19
  const { fetch, rpc_url, ...fetchOptions } = network;
20
20
 
21
- console.log(transaction_body);
22
-
23
- const pushed_txn_req = await fetch(`${rpc_url}/v1/chain/push_transaction`, {
21
+ const pushed_txn_req = await fetch(`${rpc_url}/v1/chain/send_transaction`, {
24
22
  method: "POST",
25
23
  ...fetchOptions,
26
24
  body: JSON.stringify({
@@ -0,0 +1,273 @@
1
+ import serialize from "eosio-wasm-js/serialize.mjs";
2
+
3
+ import { eosio_abi_to_graphql_ast } from "./eosio_abi_to_graphql_ast.mjs";
4
+
5
+ const ABI = {
6
+ version: "eosio::abi/1.1",
7
+ structs: [
8
+ {
9
+ name: "extensions_entry",
10
+ base: "",
11
+ fields: [
12
+ {
13
+ name: "tag",
14
+ type: "uint16"
15
+ },
16
+ {
17
+ name: "value",
18
+ type: "bytes"
19
+ }
20
+ ]
21
+ },
22
+ {
23
+ name: "type_def",
24
+ base: "",
25
+ fields: [
26
+ {
27
+ name: "new_type_name",
28
+ type: "string"
29
+ },
30
+ {
31
+ name: "type",
32
+ type: "string"
33
+ }
34
+ ]
35
+ },
36
+ {
37
+ name: "field_def",
38
+ base: "",
39
+ fields: [
40
+ {
41
+ name: "name",
42
+ type: "string"
43
+ },
44
+ {
45
+ name: "type",
46
+ type: "string"
47
+ }
48
+ ]
49
+ },
50
+ {
51
+ name: "struct_def",
52
+ base: "",
53
+ fields: [
54
+ {
55
+ name: "name",
56
+ type: "string"
57
+ },
58
+ {
59
+ name: "base",
60
+ type: "string"
61
+ },
62
+ {
63
+ name: "fields",
64
+ type: "field_def[]"
65
+ }
66
+ ]
67
+ },
68
+ {
69
+ name: "action_def",
70
+ base: "",
71
+ fields: [
72
+ {
73
+ name: "name",
74
+ type: "name"
75
+ },
76
+ {
77
+ name: "type",
78
+ type: "string"
79
+ },
80
+ {
81
+ name: "ricardian_contract",
82
+ type: "string"
83
+ }
84
+ ]
85
+ },
86
+ {
87
+ name: "table_def",
88
+ base: "",
89
+ fields: [
90
+ {
91
+ name: "name",
92
+ type: "name"
93
+ },
94
+ {
95
+ name: "index_type",
96
+ type: "string"
97
+ },
98
+ {
99
+ name: "key_names",
100
+ type: "string[]"
101
+ },
102
+ {
103
+ name: "key_types",
104
+ type: "string[]"
105
+ },
106
+ {
107
+ name: "type",
108
+ type: "string"
109
+ }
110
+ ]
111
+ },
112
+ {
113
+ name: "clause_pair",
114
+ base: "",
115
+ fields: [
116
+ {
117
+ name: "id",
118
+ type: "string"
119
+ },
120
+ {
121
+ name: "body",
122
+ type: "string"
123
+ }
124
+ ]
125
+ },
126
+ {
127
+ name: "error_message",
128
+ base: "",
129
+ fields: [
130
+ {
131
+ name: "error_code",
132
+ type: "uint64"
133
+ },
134
+ {
135
+ name: "error_msg",
136
+ type: "string"
137
+ }
138
+ ]
139
+ },
140
+ {
141
+ name: "variant_def",
142
+ base: "",
143
+ fields: [
144
+ {
145
+ name: "name",
146
+ type: "string"
147
+ },
148
+ {
149
+ name: "types",
150
+ type: "string[]"
151
+ }
152
+ ]
153
+ },
154
+ {
155
+ name: "abi_def",
156
+ base: "",
157
+ fields: [
158
+ {
159
+ name: "version",
160
+ type: "string"
161
+ },
162
+ {
163
+ name: "types",
164
+ type: "type_def[]"
165
+ },
166
+ {
167
+ name: "structs",
168
+ type: "struct_def[]"
169
+ },
170
+ {
171
+ name: "actions",
172
+ type: "action_def[]"
173
+ },
174
+ {
175
+ name: "tables",
176
+ type: "table_def[]"
177
+ },
178
+ {
179
+ name: "ricardian_clauses",
180
+ type: "clause_pair[]"
181
+ },
182
+ {
183
+ name: "error_messages",
184
+ type: "error_message[]"
185
+ },
186
+ {
187
+ name: "abi_extensions",
188
+ type: "extensions_entry[]"
189
+ },
190
+ {
191
+ name: "variants",
192
+ type: "variant_def[]$"
193
+ }
194
+ ]
195
+ }
196
+ ]
197
+ };
198
+
199
+ const AST = eosio_abi_to_graphql_ast(ABI);
200
+
201
+ /**
202
+ * Given a Smart contract convert the ABI to serialized byte code representation.
203
+ * @param {Object} abi JS Object of the Antelope ABI for a given smart contract.
204
+ * @returns {String} serialized Byte code representation of the ABI.
205
+ */
206
+ export default async function serialize_abi(abi) {
207
+ let JSON_ABI = abi;
208
+
209
+ ABI.structs[9].fields.forEach(({ name }) => {
210
+ if (JSON_ABI[name] == undefined) {
211
+ JSON_ABI[name] = [];
212
+ }
213
+ });
214
+
215
+ const build_serialize_list = async (data, instructions) => {
216
+ const serialize_list = [];
217
+
218
+ for (const instruction of instructions) {
219
+ const { $info, name, type } = instruction;
220
+ const datum = data[name];
221
+
222
+ const next_instruction = AST[type];
223
+
224
+ if ($info.variant) {
225
+ if (Object.keys(data).length > 1)
226
+ throw new Error(`Must only include one type for variant.`);
227
+ if (!datum) continue;
228
+ else
229
+ serialize_list.push({
230
+ type: "varuint32",
231
+ value: instructions.findIndex((i) => i.type == type)
232
+ });
233
+ }
234
+
235
+ if ($info.binary_ex) $info.optional = false; // Binary extentions are optional (GraphQL types) but should not serialize an optional type.
236
+
237
+ if ($info.optional)
238
+ serialize_list.push({ type: "bool", value: datum != undefined }); // Add an optional item to serialize list.
239
+
240
+ if ($info.list)
241
+ if (datum !== undefined)
242
+ serialize_list.push({ type: "varuint32", value: datum.length }); // Add an length of list to serialize list.
243
+
244
+ // Indicates that we need to recursion loop through each data item.
245
+ if (next_instruction)
246
+ if ($info.list) {
247
+ if (datum != undefined && !$info.binary_ex)
248
+ for await (const d of datum)
249
+ serialize_list.push(
250
+ ...(await build_serialize_list(await d, next_instruction))
251
+ );
252
+ }
253
+ // None list recursion
254
+ else
255
+ serialize_list.push(
256
+ ...(await build_serialize_list(datum, next_instruction))
257
+ );
258
+ // Indicates that the list of data can be serilaized and so is pushed into serialize_list.
259
+ else if ($info.list && datum !== undefined)
260
+ for await (const d of datum) serialize_list.push({ type, value: d });
261
+ else if (datum !== undefined) serialize_list.push({ type, value: datum }); // Native eoio types than can be serialized.
262
+ }
263
+
264
+ return serialize_list;
265
+ };
266
+
267
+ const ser_list = await build_serialize_list(JSON_ABI, AST.abi_def);
268
+
269
+ let hex_string = "";
270
+ ser_list.forEach(({ type, value }) => (hex_string += serialize[type](value)));
271
+
272
+ return hex_string;
273
+ }
@@ -1,5 +1,6 @@
1
- import { GraphQLNonNull } from "graphql";
1
+ import { GraphQLList, GraphQLNonNull } from "graphql";
2
2
 
3
+ import public_key_type from "./eosio_types/public_key_type.mjs";
3
4
  import configuration_type from "./graphql_input_types/configuration.mjs";
4
5
  import packed_transaction_type from "./graphql_object_types/packed_transaction.mjs";
5
6
  import mutation_resolver from "./mutation_resolver.mjs";
@@ -13,10 +14,19 @@ const serialize_transaction = (actions, ast_list) => ({
13
14
  },
14
15
  configuration: {
15
16
  type: configuration_type
17
+ },
18
+ available_keys: {
19
+ type: new GraphQLList(public_key_type)
16
20
  }
17
21
  },
18
- resolve(_, args, { network }) {
19
- return mutation_resolver(args, network, ast_list);
22
+ async resolve(_, { available_keys, ...args }, { network }) {
23
+ const { transaction, ...serialized_txn } = await mutation_resolver(
24
+ args,
25
+ network,
26
+ ast_list
27
+ );
28
+
29
+ return { ...serialized_txn, available_keys, transaction };
20
30
  }
21
31
  });
22
32