├── .babelrc
├── .ci
├── travis-before-install.sh
├── travis-before-script.sh
└── travis-install.sh
├── .eslintignore
├── .eslintrc.js
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── .husky
└── .gitignore
├── .npmignore
├── .travis.yml
├── API.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.rst
├── LICENSE
├── LICENSE-docs
├── README.md
├── RELEASE_PROCESS.md
├── compose
├── Dockerfile
└── tendermint
│ └── tmdata
│ └── config.toml
├── docker-compose.yml
├── docs
├── Makefile
├── README.md
├── make.bat
├── requirements.txt
├── source
│ ├── .conf.py.swp
│ ├── advanced.rst
│ ├── conf.py
│ ├── index.rst
│ ├── quickstart.rst
│ ├── readme.rst
│ └── usage.rst
└── upgrade-guides
│ └── 0.3.0.md
├── examples
├── .babelrc
├── .gitignore
├── README.md
├── package.json
└── src
│ ├── basic-usage-async-await.js
│ ├── basic-usage.js
│ ├── query-assets.js
│ └── seed-func.js
├── media
├── repo-banner.sketch
└── repo-banner@2x.png
├── package.json
├── plugins
└── add-vendors-plugin.js
├── src
├── Ed25519Keypair.js
├── baseRequest.js
├── connection.js
├── format_text.js
├── index.js
├── request.js
├── sanitize.js
├── sha256Hash.js
├── stringify_as_query_param.js
├── transaction.js
├── transport.js
└── utils
│ ├── ccJsonLoad.js
│ └── ccJsonify.js
├── test
├── base-request
│ └── test_baseRequest.js
├── connection
│ └── test_connection.js
├── constants.js
├── integration
│ └── test_integration.js
├── request
│ └── test_request.js
├── sanitize
│ └── test_sanitize.js
├── text-format
│ └── test_format_text.js
├── transaction
│ ├── test_cryptoconditions.js
│ └── test_transaction.js
└── transport
│ └── test_transport.js
├── types
├── Ed25519Keypair.d.ts
├── baseRequest.d.ts
├── connection.d.ts
├── index.d.ts
├── request.d.ts
├── sanitize.d.ts
├── transaction.d.ts
├── transport.d.ts
└── utils
│ ├── ccJsonLoad.d.ts
│ └── ccJsonify.d.ts
├── webpack.common.js
├── webpack.config.js
├── webpack.development.js
├── webpack.parts.js
└── webpack.production.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | [
4 | "@babel/preset-env",
5 | {
6 | "targets": [
7 | "> 0.25%, not dead",
8 | "not IE 11",
9 | "maintained node versions"
10 | ]
11 | }
12 | ]
13 | ],
14 | "plugins": [
15 | "@babel/plugin-proposal-export-default-from",
16 | "@babel/plugin-transform-object-assign",
17 | "@babel/plugin-proposal-object-rest-spread",
18 | [
19 | "@babel/plugin-transform-runtime",
20 | {
21 | "absoluteRuntime": false,
22 | "corejs": 3,
23 | "helpers": true,
24 | "regenerator": true
25 | }
26 | ]
27 | ],
28 | "sourceMaps": true
29 | }
30 |
--------------------------------------------------------------------------------
/.ci/travis-before-install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright BigchainDB GmbH and BigchainDB contributors
3 | # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4 | # Code is Apache-2.0 and docs are CC-BY-4.0
5 |
6 |
7 | sudo apt-get update
8 | sudo apt-get -y -o Dpkg::Options::="--force-confnew" install docker-ce
9 |
10 | sudo rm /usr/local/bin/docker-compose
11 | curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
12 | chmod +x docker-compose
13 | sudo mv docker-compose /usr/local/bin
14 |
--------------------------------------------------------------------------------
/.ci/travis-before-script.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright BigchainDB GmbH and BigchainDB contributors
3 | # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4 | # Code is Apache-2.0 and docs are CC-BY-4.0
5 |
6 |
7 | set -e -x
8 |
9 | docker-compose up -d bigchaindb
10 |
11 | npm install
12 | gem install cowsay
13 | npm install -g codecov
--------------------------------------------------------------------------------
/.ci/travis-install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Copyright BigchainDB GmbH and BigchainDB contributors
3 | # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4 | # Code is Apache-2.0 and docs are CC-BY-4.0
5 |
6 |
7 | set -e -x
8 |
9 | docker-compose build --no-cache bigchaindb
10 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 | coverage
4 | media
5 | docs
6 | compose
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ['eslint:recommended', 'airbnb-base', 'plugin:import/recommended'],
3 | parser: '@babel/eslint-parser',
4 | parserOptions: { requireConfigFile: false },
5 | env: {
6 | browser: true,
7 | node: true,
8 | },
9 | settings: {
10 | 'import/ignore': ['node_modules', '.(scss|css)$', '.(jpe?g|png|gif|svg)'],
11 | },
12 | rules: {
13 | /**
14 | * Possible Errors
15 | * http://eslint.org/docs/rus/#possible-errors
16 | */
17 |
18 | // Allow dangling commas for multiline arrays and objects
19 | // http://eslint.org/docs/rules/comma-dangle
20 | 'comma-dangle': [1, 'only-multiline'],
21 |
22 | // Warn against use of console for non-error logging
23 | // http://eslint.org/docs/rules/no-console
24 | 'no-console': [1, { allow: ['error'] }],
25 |
26 | // Allow use of Object.prototypes builtins directly
27 | // http://eslint.org/docs/rules/no-prototype-builtins
28 | 'no-prototype-builtins': [0],
29 |
30 | /**
31 | * Best Practices
32 | * http://eslint.org/docs/rules/#best-practices
33 | */
34 |
35 | // Allow else clauses after an if with a return
36 | // http://eslint.org/docs/rules/no-else-return
37 | 'no-else-return': [0],
38 |
39 | // Disallow reassignment of function parameters (but allow assigning to parameter's properties)
40 | // http://eslint.org/docs/rules/no-param-reassign.html
41 | 'no-param-reassign': [2, { props: false }],
42 |
43 | /**
44 | * Variables
45 | * http://eslint.org/docs/rules/#variables
46 | */
47 |
48 | // Disallow use of variables and classes before they are defined
49 | // http://eslint.org/docs/rules/no-use-before-define
50 | 'no-use-before-define': [2, { functions: false, classes: true }],
51 |
52 | // Disallow declaration of variables that are not used in the code, unless they are prefixed by
53 | // `ignored` (useful for creating subset objects through destructuring and rest objects)
54 | // http://eslint.org/docs/rules/no-unused-vars
55 | 'no-unused-vars': [
56 | 2,
57 | {
58 | vars: 'local',
59 | args: 'after-used',
60 | varsIgnorePattern: 'ignored.+',
61 | },
62 | ],
63 |
64 | /**
65 | * Stylelistic Issues
66 | * (http://eslint.org/docs/rules/#stylistic-issues)
67 | */
68 |
69 | // Enforce 4-space indents, except for switch cases
70 | // http://eslint.org/docs/rules/indent
71 | 'indent': [2, 4, { SwitchCase: 1, VariableDeclarator: 1 }],
72 |
73 | // Specify the maximum length of a code line to be 100
74 | // http://eslint.org/docs/rules/max-len
75 | 'max-len': [
76 | 2,
77 | {
78 | code: 105, // Use 105 to give some leeway for *just* slightly longer lines when convienient
79 | ignorePattern: '^(import|export) .* from .*$',
80 | ignoreComments: false,
81 | ignoreTrailingComments: true,
82 | ignoreUrls: true,
83 | },
84 | ],
85 |
86 | // Require capitalization when using `new`, but don't require capitalized functions to be called
87 | // with new
88 | // http://eslint.org/docs/rules/new-cap
89 | 'new-cap': [2, { newIsCap: true, capIsNew: false }],
90 |
91 | // Allow the continue statement
92 | // http://eslint.org/docs/rules/no-continue
93 | 'no-continue': [0],
94 |
95 | // Disallow un-paren'd mixes of different operators if they're not of the same precendence
96 | // http://eslint.org/docs/rules/no-mixed-operators
97 | 'no-mixed-operators': [
98 | 2,
99 | {
100 | groups: [
101 | ['+', '-', '*', '/', '%', '**'],
102 | ['&', '|', '^', '~', '<<', '>>', '>>>'],
103 | ['==', '!=', '===', '!==', '>', '>=', '<', '<='],
104 | ['&&', '||'],
105 | ['in', 'instanceof'],
106 | ],
107 | allowSamePrecedence: true,
108 | },
109 | ],
110 |
111 | // Allow use of unary increment/decrement operators
112 | // http://eslint.org/docs/rules/no-plusplus
113 | 'no-plusplus': [0],
114 |
115 | // Always allow dangling underscores
116 | // http://eslint.org/docs/rules/no-underscore-dangle
117 | 'no-underscore-dangle': [0],
118 |
119 | // Require unix-style line breaks
120 | // http://eslint.org/docs/rules/linebreak-style
121 | 'linebreak-style': [2, 'unix'],
122 |
123 | // Require operators to always be at the end of a line, except for the ternary operator
124 | // http://eslint.org/docs/rules/operator-linebreak
125 | 'operator-linebreak': [
126 | 2,
127 | 'after',
128 | { overrides: { '?': 'ignore', ':': 'ignore' } },
129 | ],
130 |
131 | // Require properties to be consistently quoted. Force numbers to be quoted, as they can have
132 | // weird behaviour during the coercion into a string)
133 | // http://eslint.org/docs/rules/quote-props
134 | 'quote-props': [
135 | 2,
136 | 'consistent',
137 | { keywords: false, unnecessary: true, numbers: true },
138 | ],
139 |
140 | // Require spaces before parens for anonymous function declarations
141 | // http://eslint.org/docs/rules/space-before-function-paren
142 | 'space-before-function-paren': [2, { anonymous: 'always', named: 'never' }],
143 |
144 | // Require a space immediately following the // or /* in a comment for most comments
145 | // http://eslint.org/docs/rules/spaced-comment
146 | 'spaced-comment': [
147 | 2,
148 | 'always',
149 | {
150 | line: {
151 | exceptions: ['-', '+'],
152 | },
153 | block: {
154 | exceptions: ['*'],
155 | },
156 | },
157 | ],
158 |
159 | // We don't like semicolons so kill them
160 | // http://eslint.org/docs/rules/semi
161 | 'semi': [2, 'never'],
162 |
163 | /**
164 | * Import rules
165 | * https://github.com/benmosher/eslint-plugin-import#rules
166 | */
167 |
168 | // Ensure named imports coupled with named exports
169 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/named.md#when-not-to-use-it
170 | 'import/named': 2,
171 |
172 | // Ensure default import coupled with default export
173 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/default.md#when-not-to-use-it
174 | 'import/default': 2,
175 |
176 | // Disallow namespace (wildcard) imports
177 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/no-namespace.md
178 | 'import/no-namespace': 2,
179 |
180 | // Enforce imports to not specify a trailing .js extension
181 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/extensions.md
182 | 'import/extensions': [2, { js: 'never' }],
183 |
184 | // Enforce module import order: builtin -> external -> internal
185 | // https://github.com/benmosher/eslint-plugin-import/blob/master/docs/rules/order.md
186 | 'import/order': [
187 | 2,
188 | {
189 | groups: [
190 | 'builtin',
191 | 'external',
192 | ['internal', 'parent', 'sibling', 'index'],
193 | ],
194 | },
195 | ],
196 | 'import/no-extraneous-dependencies': ['error', { 'devDependencies': true }],
197 | /**
198 | * ES6-specific Issues
199 | * (http://eslint.org/docs/rules/#ecmascript-6)
200 | */
201 | 'arrow-body-style': [0],
202 | 'arrow-parens': [0],
203 | 'arrow-spacing': [0],
204 | 'constructor-super': [0],
205 | 'generator-star-spacing': [0],
206 | 'no-class-assign': [0],
207 | 'no-confusing-arrow': [0],
208 | 'no-const-assign': [0],
209 | 'no-dupe-class-members': [0],
210 | 'no-duplicate-imports': [0],
211 | 'no-new-symbol': [0],
212 | 'no-restricted-imports': [0],
213 | 'no-this-before-super': [0],
214 | 'no-useless-computed-key': [0],
215 | 'no-useless-constructor': [0],
216 | 'no-useless-rename': [0],
217 | 'no-var': [0],
218 | 'object-shorthand': [0],
219 | 'prefer-arrow-callback': [0],
220 | 'prefer-const': [0],
221 | 'prefer-reflect': [0],
222 | 'prefer-rest-params': [0],
223 | 'prefer-spread': [0],
224 | 'prefer-template': [0],
225 | 'require-yield': [0],
226 | 'rest-spread-spacing': [0],
227 | 'sort-imports': [0],
228 | 'template-curly-spacing': [0],
229 | 'yield-star-spacing': [0],
230 | },
231 | }
232 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | paths-ignore:
8 | - README.md
9 | - API.md
10 | - docs/*.rst
11 | pull_request:
12 | branches:
13 | - master
14 | types:
15 | - ready_for_review
16 | - opened
17 | - reopened
18 | - synchronize
19 | paths-ignore:
20 | - README.md
21 | - API.md
22 | - docs/*.rst
23 |
24 | jobs:
25 | test:
26 | runs-on: ubuntu-latest
27 | if: github.event_name == 'release' || github.event_name == 'push' || !github.event.pull_request.draft
28 | timeout-minutes: 10
29 |
30 | steps:
31 | - name: Checkout the commit
32 | uses: actions/checkout@v2
33 |
34 | - name: Set up Node
35 | uses: actions/setup-node@v2
36 | with:
37 | node-version: 14
38 |
39 | - name: Cache dependencies
40 | id: cache
41 | uses: actions/cache@v2
42 | with:
43 | path: ~/.npm
44 | key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
45 | restore-keys: |
46 | ${{ runner.os }}-node-
47 |
48 | - name: Run BigChainDB node
49 | run: |
50 | echo Building and starting up docker containers
51 | docker-compose -f ./docker-compose.yml up -d
52 |
53 | - name: Install dependencies
54 | env:
55 | HUSKY_SKIP_INSTALL: 'true'
56 | run: npm install
57 |
58 | - name: Lint
59 | run: npm run lint
60 |
61 | - name: Build
62 | run: npm run build
63 |
64 | # ensure BCDB node is up and running
65 | - run: sleep 20
66 |
67 | - name: Test
68 | run: npm run test
69 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.seed
2 | *.log
3 | *.dat
4 | *.out
5 | *.pid
6 | *.gz
7 | .idea
8 | *.sublime-project
9 | *.sublime-workspace
10 | *.sublime-workspace
11 | .DS_Store
12 | .vscode
13 |
14 | .env
15 | .genv
16 |
17 | node_modules
18 | dist
19 | package-lock.json
20 | coverage
21 | coverage.lcov
22 | .nyc_output
23 | yarn.lock
24 | docs/build/
25 | docs/_build/
26 | docs/build/
27 |
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | *.seed
2 | *.log
3 | *.dat
4 | *.out
5 | *.pid
6 | *.gz
7 | .idea
8 | *.sublime-project
9 | *.sublime-workspace
10 | *.sublime-workspace
11 | .DS_Store
12 | .vscode
13 |
14 | .env
15 | .genv
16 |
17 | node_modules
18 | package-lock.json
19 | coverage
20 | coverage.lcov
21 | .nyc_output
22 | yarn.lock
23 |
24 | docs/build/
25 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Copyright BigchainDB GmbH and BigchainDB contributors
2 | # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | # Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | sudo: required
6 |
7 | services:
8 | - docker
9 |
10 | language: node_js
11 |
12 | node_js:
13 | - 10
14 | - 12
15 | - 14
16 |
17 | cache:
18 | directories:
19 | - node_modules
20 |
21 | env:
22 | global:
23 | - DOCKER_COMPOSE_VERSION=1.28.5
24 |
25 | before_install:
26 | - .ci/travis-before-install.sh
27 |
28 | install:
29 | - .ci/travis-install.sh
30 |
31 | before_script:
32 | - .ci/travis-before-script.sh
33 |
34 | script: npm test
35 |
36 | notifications:
37 | email: false
38 |
--------------------------------------------------------------------------------
/API.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ### Table of Contents
4 |
5 | - [Ed25519Keypair][1]
6 | - [Parameters][2]
7 | - [Properties][3]
8 | - [Connection][4]
9 | - [Parameters][5]
10 | - [getBlock][6]
11 | - [Parameters][7]
12 | - [getTransaction][8]
13 | - [Parameters][9]
14 | - [listBlocks][10]
15 | - [Parameters][11]
16 | - [listOutputs][12]
17 | - [Parameters][13]
18 | - [listTransactions][14]
19 | - [Parameters][15]
20 | - [postTransaction][16]
21 | - [Parameters][17]
22 | - [postTransactionSync][18]
23 | - [Parameters][19]
24 | - [postTransactionAsync][20]
25 | - [Parameters][21]
26 | - [postTransactionCommit][22]
27 | - [Parameters][23]
28 | - [searchAssets][24]
29 | - [Parameters][25]
30 | - [searchMetadata][26]
31 | - [Parameters][27]
32 | - [Transaction][28]
33 | - [serializeTransactionIntoCanonicalString][29]
34 | - [Parameters][30]
35 | - [makeCreateTransaction][31]
36 | - [Parameters][32]
37 | - [makeEd25519Condition][33]
38 | - [Parameters][34]
39 | - [makeOutput][35]
40 | - [Parameters][36]
41 | - [makeSha256Condition][37]
42 | - [Parameters][38]
43 | - [makeThresholdCondition][39]
44 | - [Parameters][40]
45 | - [makeTransferTransaction][41]
46 | - [Parameters][42]
47 | - [signTransaction][43]
48 | - [Parameters][44]
49 | - [delegateSignTransaction][45]
50 | - [Parameters][46]
51 | - [delegateSignTransactionAsync][47]
52 | - [Parameters][48]
53 | - [ccJsonLoad][49]
54 | - [Parameters][50]
55 | - [ccJsonify][51]
56 | - [Parameters][52]
57 |
58 | ## Ed25519Keypair
59 |
60 | [src/Ed25519Keypair.js:16-21][53]
61 |
62 | Type: [Object][54]
63 |
64 | ### Parameters
65 |
66 | - `seed` **[Buffer][55]?** A seed that will be used as a key derivation function
67 |
68 | ### Properties
69 |
70 | - `publicKey` **[string][56]**
71 | - `privateKey` **[string][56]**
72 |
73 | ## Connection
74 |
75 | [src/connection.js:21-199][57]
76 |
77 | ### Parameters
78 |
79 | - `nodes`
80 | - `headers` **[Object][54]** Common headers for every request (optional, default `{}`)
81 | - `timeout` **float** Optional timeout in secs (optional, default `DEFAULT_TIMEOUT`)
82 |
83 | ### getBlock
84 |
85 | [src/connection.js:79-85][58]
86 |
87 | #### Parameters
88 |
89 | - `blockHeight`
90 |
91 | ### getTransaction
92 |
93 | [src/connection.js:90-96][59]
94 |
95 | #### Parameters
96 |
97 | - `transactionId`
98 |
99 | ### listBlocks
100 |
101 | [src/connection.js:102-108][60]
102 |
103 | #### Parameters
104 |
105 | - `transactionId`
106 | - `status`
107 |
108 | ### listOutputs
109 |
110 | [src/connection.js:114-126][61]
111 |
112 | #### Parameters
113 |
114 | - `publicKey`
115 | - `spent`
116 |
117 | ### listTransactions
118 |
119 | [src/connection.js:132-139][62]
120 |
121 | #### Parameters
122 |
123 | - `assetId`
124 | - `operation`
125 |
126 | ### postTransaction
127 |
128 | [src/connection.js:144-146][63]
129 |
130 | #### Parameters
131 |
132 | - `transaction`
133 |
134 | ### postTransactionSync
135 |
136 | [src/connection.js:151-156][64]
137 |
138 | #### Parameters
139 |
140 | - `transaction`
141 |
142 | ### postTransactionAsync
143 |
144 | [src/connection.js:161-166][65]
145 |
146 | #### Parameters
147 |
148 | - `transaction`
149 |
150 | ### postTransactionCommit
151 |
152 | [src/connection.js:171-176][66]
153 |
154 | #### Parameters
155 |
156 | - `transaction`
157 |
158 | ### searchAssets
159 |
160 | [src/connection.js:181-187][67]
161 |
162 | #### Parameters
163 |
164 | - `search`
165 |
166 | ### searchMetadata
167 |
168 | [src/connection.js:192-198][68]
169 |
170 | #### Parameters
171 |
172 | - `search`
173 |
174 | ## Transaction
175 |
176 | [src/transaction.js:16-288][69]
177 |
178 | Construct Transactions
179 |
180 | ### serializeTransactionIntoCanonicalString
181 |
182 | [src/transaction.js:22-29][70]
183 |
184 | Canonically serializes a transaction into a string by sorting the keys
185 |
186 | #### Parameters
187 |
188 | - `transaction`
189 | - `null` **[Object][54]** (transaction)
190 |
191 | Returns **[string][56]** a canonically serialized Transaction
192 |
193 | ### makeCreateTransaction
194 |
195 | [src/transaction.js:80-87][71]
196 |
197 | Generate a `CREATE` transaction holding the `asset`, `metadata`, and `outputs`, to be signed by
198 | the `issuers`.
199 |
200 | #### Parameters
201 |
202 | - `asset` **[Object][54]** Created asset's data
203 | - `metadata` **[Object][54]** Metadata for the Transaction
204 | - `outputs` **[Array][72]<[Object][54]>** Array of Output objects to add to the Transaction.
205 | Think of these as the recipients of the asset after the transaction.
206 | For `CREATE` Transactions, this should usually just be a list of
207 | Outputs wrapping Ed25519 Conditions generated from the issuers' public
208 | keys (so that the issuers are the recipients of the created asset).
209 | - `issuers` **...[Array][72]<[string][56]>** Public key of one or more issuers to the asset being created by this
210 | Transaction.
211 | Note: Each of the private keys corresponding to the given public
212 | keys MUST be used later (and in the same order) when signing the
213 | Transaction (`signTransaction()`).
214 |
215 | Returns **[Object][54]** Unsigned transaction -- make sure to call signTransaction() on it before
216 | sending it off!
217 |
218 | ### makeEd25519Condition
219 |
220 | [src/transaction.js:96-101][73]
221 |
222 | Create an Ed25519 Cryptocondition from an Ed25519 public key
223 | to put into an Output of a Transaction
224 |
225 | #### Parameters
226 |
227 | - `publicKey` **[string][56]** base58 encoded Ed25519 public key for the recipient of the Transaction
228 | - `json` **[boolean][74]** If true returns a json object otherwise a crypto-condition type (optional, default `true`)
229 |
230 | Returns **[Object][54]** Ed25519 Condition (that will need to wrapped in an Output)
231 |
232 | ### makeOutput
233 |
234 | [src/transaction.js:111-131][75]
235 |
236 | Create an Output from a Condition.
237 | Note: Assumes the given Condition was generated from a
238 | single public key (e.g. a Ed25519 Condition)
239 |
240 | #### Parameters
241 |
242 | - `condition` **[Object][54]** Condition (e.g. a Ed25519 Condition from `makeEd25519Condition()`)
243 | - `amount` **[string][56]** Amount of the output (optional, default `'1'`)
244 |
245 | Returns **[Object][54]** An Output usable in a Transaction
246 |
247 | ### makeSha256Condition
248 |
249 | [src/transaction.js:139-143][76]
250 |
251 | Create a Preimage-Sha256 Cryptocondition from a secret to put into an Output of a Transaction
252 |
253 | #### Parameters
254 |
255 | - `preimage` **[string][56]** Preimage to be hashed and wrapped in a crypto-condition
256 | - `json` **[boolean][74]** If true returns a json object otherwise a crypto-condition type (optional, default `true`)
257 |
258 | Returns **[Object][54]** Preimage-Sha256 Condition (that will need to wrapped in an Output)
259 |
260 | ### makeThresholdCondition
261 |
262 | [src/transaction.js:152-162][77]
263 |
264 | Create an Sha256 Threshold Cryptocondition from threshold to put into an Output of a Transaction
265 |
266 | #### Parameters
267 |
268 | - `threshold` **[number][78]**
269 | - `subconditions` **[Array][72]** (optional, default `[]`)
270 | - `json` **[boolean][74]** If true returns a json object otherwise a crypto-condition type (optional, default `true`)
271 |
272 | Returns **[Object][54]** Sha256 Threshold Condition (that will need to wrapped in an Output)
273 |
274 | ### makeTransferTransaction
275 |
276 | [src/transaction.js:185-206][79]
277 |
278 | Generate a `TRANSFER` transaction holding the `asset`, `metadata`, and `outputs`, that fulfills
279 | the `fulfilledOutputs` of `unspentTransaction`.
280 |
281 | #### Parameters
282 |
283 | - `unspentOutputs`
284 | - `outputs` **[Array][72]<[Object][54]>** Array of Output objects to add to the Transaction.
285 | Think of these as the recipients of the asset after the transaction.
286 | For `TRANSFER` Transactions, this should usually just be a list of
287 | Outputs wrapping Ed25519 Conditions generated from the public keys of
288 | the recipients.
289 | - `metadata` **[Object][54]** Metadata for the Transaction
290 | - `unspentTransaction` **[Object][54]** Previous Transaction you have control over (i.e. can fulfill
291 | its Output Condition)
292 | - `OutputIndices` **...[number][78]** Indices of the Outputs in `unspentTransaction` that this
293 | Transaction fulfills.
294 | Note that listed public keys listed must be used (and in
295 | the same order) to sign the Transaction
296 | (`signTransaction()`).
297 |
298 | Returns **[Object][54]** Unsigned transaction -- make sure to call signTransaction() on it before
299 | sending it off!
300 |
301 | ### signTransaction
302 |
303 | [src/transaction.js:219-243][80]
304 |
305 | Sign the given `transaction` with the given `privateKey`s, returning a new copy of `transaction`
306 | that's been signed.
307 | Note: Only generates Ed25519 Fulfillments. Thresholds and other types of Fulfillments are left as
308 | an exercise for the user.
309 |
310 | #### Parameters
311 |
312 | - `transaction` **[Object][54]** Transaction to sign. `transaction` is not modified.
313 | - `privateKeys` **...[string][56]** Private keys associated with the issuers of the `transaction`.
314 | Looped through to iteratively sign any Input Fulfillments found in
315 | the `transaction`.
316 |
317 | Returns **[Object][54]** The signed version of `transaction`.
318 |
319 | ### delegateSignTransaction
320 |
321 | [src/transaction.js:252-265][81]
322 |
323 | Delegate signing of the given `transaction` returning a new copy of `transaction`
324 | that's been signed.
325 |
326 | #### Parameters
327 |
328 | - `transaction` **[Object][54]** Transaction to sign. `transaction` is not modified.
329 | - `signFn` **[Function][82]** Function signing the transaction, expected to return the fulfillment.
330 |
331 | Returns **[Object][54]** The signed version of `transaction`.
332 |
333 | ### delegateSignTransactionAsync
334 |
335 | [src/transaction.js:274-287][83]
336 |
337 | Delegate signing of the given `transaction` returning a new copy of `transaction`
338 | that's been signed.
339 |
340 | #### Parameters
341 |
342 | - `transaction` **[Object][54]** Transaction to sign. `transaction` is not modified.
343 | - `signFn` **[Function][82]** Function signing the transaction, expected to resolve the fulfillment.
344 |
345 | Returns **[Promise][84]<[Object][54]>** The signed version of `transaction`.
346 |
347 | ## ccJsonLoad
348 |
349 | [src/utils/ccJsonLoad.js:13-44][85]
350 |
351 | Loads a crypto-condition class (Fulfillment or Condition) from a BigchainDB JSON object
352 |
353 | ### Parameters
354 |
355 | - `conditionJson` **[Object][54]**
356 |
357 | Returns **cc.Condition** Ed25519 Condition (that will need to wrapped in an Output)
358 |
359 | ## ccJsonify
360 |
361 | [src/utils/ccJsonify.js:12-65][86]
362 |
363 | Serializes a crypto-condition class (Condition or Fulfillment) into a BigchainDB-compatible JSON
364 |
365 | ### Parameters
366 |
367 | - `fulfillment` **cc.Fulfillment** base58 encoded Ed25519 public key for recipient of the Transaction
368 |
369 | Returns **[Object][54]** Ed25519 Condition (that will need to wrapped in an Output)
370 |
371 | [1]: #ed25519keypair
372 |
373 | [2]: #parameters
374 |
375 | [3]: #properties
376 |
377 | [4]: #connection
378 |
379 | [5]: #parameters-1
380 |
381 | [6]: #getblock
382 |
383 | [7]: #parameters-2
384 |
385 | [8]: #gettransaction
386 |
387 | [9]: #parameters-3
388 |
389 | [10]: #listblocks
390 |
391 | [11]: #parameters-4
392 |
393 | [12]: #listoutputs
394 |
395 | [13]: #parameters-5
396 |
397 | [14]: #listtransactions
398 |
399 | [15]: #parameters-6
400 |
401 | [16]: #posttransaction
402 |
403 | [17]: #parameters-7
404 |
405 | [18]: #posttransactionsync
406 |
407 | [19]: #parameters-8
408 |
409 | [20]: #posttransactionasync
410 |
411 | [21]: #parameters-9
412 |
413 | [22]: #posttransactioncommit
414 |
415 | [23]: #parameters-10
416 |
417 | [24]: #searchassets
418 |
419 | [25]: #parameters-11
420 |
421 | [26]: #searchmetadata
422 |
423 | [27]: #parameters-12
424 |
425 | [28]: #transaction
426 |
427 | [29]: #serializetransactionintocanonicalstring
428 |
429 | [30]: #parameters-13
430 |
431 | [31]: #makecreatetransaction
432 |
433 | [32]: #parameters-14
434 |
435 | [33]: #makeed25519condition
436 |
437 | [34]: #parameters-15
438 |
439 | [35]: #makeoutput
440 |
441 | [36]: #parameters-16
442 |
443 | [37]: #makesha256condition
444 |
445 | [38]: #parameters-17
446 |
447 | [39]: #makethresholdcondition
448 |
449 | [40]: #parameters-18
450 |
451 | [41]: #maketransfertransaction
452 |
453 | [42]: #parameters-19
454 |
455 | [43]: #signtransaction
456 |
457 | [44]: #parameters-20
458 |
459 | [45]: #delegatesigntransaction
460 |
461 | [46]: #parameters-21
462 |
463 | [47]: #delegatesigntransactionasync
464 |
465 | [48]: #parameters-22
466 |
467 | [49]: #ccjsonload
468 |
469 | [50]: #parameters-23
470 |
471 | [51]: #ccjsonify
472 |
473 | [52]: #parameters-24
474 |
475 | [53]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/Ed25519Keypair.js#L16-L21 "Source code on GitHub"
476 |
477 | [54]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object
478 |
479 | [55]: https://nodejs.org/api/buffer.html
480 |
481 | [56]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
482 |
483 | [57]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L21-L199 "Source code on GitHub"
484 |
485 | [58]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L79-L85 "Source code on GitHub"
486 |
487 | [59]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L90-L96 "Source code on GitHub"
488 |
489 | [60]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L102-L108 "Source code on GitHub"
490 |
491 | [61]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L114-L126 "Source code on GitHub"
492 |
493 | [62]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L132-L139 "Source code on GitHub"
494 |
495 | [63]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L144-L146 "Source code on GitHub"
496 |
497 | [64]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L151-L156 "Source code on GitHub"
498 |
499 | [65]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L161-L166 "Source code on GitHub"
500 |
501 | [66]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L171-L176 "Source code on GitHub"
502 |
503 | [67]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L181-L187 "Source code on GitHub"
504 |
505 | [68]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/connection.js#L192-L198 "Source code on GitHub"
506 |
507 | [69]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L16-L288 "Source code on GitHub"
508 |
509 | [70]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L22-L29 "Source code on GitHub"
510 |
511 | [71]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L80-L87 "Source code on GitHub"
512 |
513 | [72]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array
514 |
515 | [73]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L96-L101 "Source code on GitHub"
516 |
517 | [74]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
518 |
519 | [75]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L111-L131 "Source code on GitHub"
520 |
521 | [76]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L139-L143 "Source code on GitHub"
522 |
523 | [77]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L152-L162 "Source code on GitHub"
524 |
525 | [78]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number
526 |
527 | [79]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L185-L206 "Source code on GitHub"
528 |
529 | [80]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L219-L243 "Source code on GitHub"
530 |
531 | [81]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L252-L265 "Source code on GitHub"
532 |
533 | [82]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function
534 |
535 | [83]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/transaction.js#L274-L287 "Source code on GitHub"
536 |
537 | [84]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise
538 |
539 | [85]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/utils/ccJsonLoad.js#L13-L44 "Source code on GitHub"
540 |
541 | [86]: https://github.com/bigchaindb/js-bigchaindb-driver/blob/76c877c649801f0a26351d03237e0b59c18bd3ef/src/utils/ccJsonify.js#L12-L65 "Source code on GitHub"
542 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | See [https://github.com/bigchaindb/bigchaindb/blob/master/CODE_OF_CONDUCT.md](https://github.com/bigchaindb/bigchaindb/blob/master/CODE_OF_CONDUCT.md)
8 |
--------------------------------------------------------------------------------
/CONTRIBUTING.rst:
--------------------------------------------------------------------------------
1 |
2 | .. Copyright BigchainDB GmbH and BigchainDB contributors
3 | SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4 | Code is Apache-2.0 and docs are CC-BY-4.0
5 |
6 | .. highlight:: shell
7 |
8 | ============
9 | Contributing
10 | ============
11 |
12 | Contributions are welcome, and they are greatly appreciated! Every
13 | little bit helps, and credit will always be given.
14 |
15 | You can contribute in many ways:
16 |
17 | Types of Contributions
18 | ----------------------
19 |
20 | Report Bugs
21 | ~~~~~~~~~~~
22 |
23 | Report bugs at https://github.com/bigchaindb/js-bigchaindb-driver/issues.
24 |
25 | If you are reporting a bug, please include:
26 |
27 | * Your operating system name and version.
28 | * Any details about your local setup that might be helpful in troubleshooting.
29 | * Detailed steps to reproduce the bug.
30 |
31 | Fix Bugs
32 | ~~~~~~~~
33 |
34 | Look through the GitHub issues for bugs. Anything tagged with "bug"
35 | and "help wanted" is open to whoever wants to implement it.
36 |
37 | Implement Features
38 | ~~~~~~~~~~~~~~~~~~
39 |
40 | Look through the GitHub issues for features. Anything tagged with "enhancement"
41 | and "help wanted" is open to whoever wants to implement it.
42 |
43 | Write Documentation
44 | ~~~~~~~~~~~~~~~~~~~
45 |
46 | bigchaindb-driver could always use more documentation, whether as part of the
47 | official bigchaindb-driver docs, in docstrings, or even on the web in blog posts,
48 | articles, and such.
49 |
50 | Submit Feedback
51 | ~~~~~~~~~~~~~~~
52 |
53 | The best way to send feedback is to file an issue at https://github.com/bigchaindb/js-bigchaindb-driver/issues.
54 |
55 | If you are proposing a feature:
56 |
57 | * Explain in detail how it would work.
58 | * Keep the scope as narrow as possible, to make it easier to implement.
59 | * Remember that this is a volunteer-driven project, and that contributions
60 | are welcome :)
61 |
62 | Get Started!
63 | ------------
64 |
65 | Ready to contribute? Here's how to set up `js-bigchaindb-driver`_ for local
66 | development.
67 |
68 | 1. Fork the `js-bigchaindb-driver`_ repo on GitHub.
69 | 2. Clone your fork locally and enter into the project::
70 |
71 | $ git clone git@github.com:your_name_here/js-bigchaindb-driver.git
72 | $ cd js-bigchaindb-driver/
73 |
74 | 3. Create a branch for local development::
75 |
76 | $ git checkout -b name-of-your-bugfix-or-feature
77 |
78 | Now you can make your changes locally.
79 |
80 | 4. Write tests ;-)
81 |
82 | 5. Test!
83 |
84 | 6. Commit your changes and push your branch to GitHub::
85 |
86 | $ git add .
87 | $ git commit -m "Your detailed description of your changes."
88 | $ git push origin name-of-your-bugfix-or-feature
89 |
90 | 7. Submit a pull request through the GitHub website.
91 |
92 |
93 | Pull Request Guidelines
94 | -----------------------
95 |
96 | Before you submit a pull request, check that it meets these guidelines:
97 |
98 | 1. The pull request should include tests.
99 | 2. If the pull request adds functionality, the docs should be updated. Put
100 | your new functionality into a function with a docstring, and add the
101 | feature to the list in README.rst.
102 | 3. The pull request should work for JS and node. Travis or others would be an interesting
103 | way for automate the tests...
104 |
105 |
106 | Dependency on Bigchaindb
107 | ~~~~~~~~~~~~~~~~~~~~~~~~
108 |
109 | This version is compatible from BigchainDB server v0.10.1
110 |
111 | .. _bigchaindb-driver: https://github.com/bigchaindb/js-bigchaindb-driver
112 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
--------------------------------------------------------------------------------
/LICENSE-docs:
--------------------------------------------------------------------------------
1 | The official BigchainDB documentation, _except for the short code snippets
2 | embedded within it_, is licensed under a Creative Commons Attribution-
3 | ShareAlike 4.0 International license, the full text of which can be found
4 | at http://creativecommons.org/licenses/by-sa/4.0/legalcode
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | # [](https://www.bigchaindb.com)
8 |
9 | > Official JavaScript driver for [BigchainDB](https://github.com/bigchaindb/bigchaindb) to create transactions in Node.js and the browser.
10 |
11 | [](https://gitter.im/bigchaindb/js-bigchaindb-driver?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
12 | [](https://www.npmjs.com/package/bigchaindb-driver)
13 | [](https://codecov.io/gh/bigchaindb/js-bigchaindb-driver)
14 | [](https://github.com/ascribe/javascript)
15 | [](https://travis-ci.com/bigchaindb/js-bigchaindb-driver)
16 | [](https://greenkeeper.io/)
17 |
18 | - [Main Documentation](https://docs.bigchaindb.com/projects/js-driver/en/latest/usage.html)
19 | - [Driver API reference](API.md)
20 |
21 | ## Compatibility
22 |
23 | | BigchainDB Server | BigchainDB JavaScript Driver |
24 | | ----------------- |------------------------------|
25 | | `0.10` | `0.1.x` |
26 | | `1.0.0` | `0.3.x` |
27 | | `1.3.x` | `3.x.x` |
28 | | `>= 2.0.0` | `4.x.x` |
29 |
30 | ## Breaking changes
31 |
32 | - **Version 4.0** of BigchainDB JavaScript Driver makes the driver compatible with BigchainDB 2.0. There are new functions for sending off transactions along with other changes. Check [older versions](https://docs.bigchaindb.com/projects/js-driver/en/latest/readme.html#features)
33 | - **Version 3.2** of BigchainDB JavaScript Driver introduces a new way of creating transfer transactions. Check [older versions](https://docs.bigchaindb.com/projects/js-driver/en/latest/readme.html#features)
34 |
35 | ## Table of Contents
36 |
37 | - [Installation and Usage](#installation-and-usage)
38 | - [Example: Create a transaction](#example-create-a-transaction)
39 | - [Browser usage](#browser-usage)
40 | - [BigchainDB Documentation](#bigchaindb-documentation)
41 | - [Speed Optimizations](#speed-optimizations)
42 | - [Development](#development)
43 | - [Release Process](#release-process)
44 | - [Authors](#authors)
45 | - [Licenses](#licenses)
46 |
47 | ---
48 |
49 | ## Installation and Usage
50 |
51 | ```bash
52 | npm install bigchaindb-driver
53 | ```
54 |
55 | ```js
56 | const driver = require('bigchaindb-driver')
57 | // or ES6+
58 | import driver from 'bigchaindb-driver'
59 | ```
60 |
61 | ### Example: Create a transaction
62 |
63 | ```js
64 | const driver = require('bigchaindb-driver')
65 | const base58 = require('bs58');
66 | const crypto = require('crypto');
67 | const { Ed25519Sha256 } = require('crypto-conditions');
68 |
69 | // BigchainDB server instance (e.g. https://example.com/api/v1/)
70 | const API_PATH = 'http://localhost:9984/api/v1/'
71 |
72 | // Create a new keypair.
73 | const alice = new driver.Ed25519Keypair()
74 |
75 | // Construct a transaction payload
76 | const tx = driver.Transaction.makeCreateTransaction(
77 | // Define the asset to store, in this example it is the current temperature
78 | // (in Celsius) for the city of Berlin.
79 | { city: 'Berlin, DE', temperature: 22, datetime: new Date().toString() },
80 |
81 | // Metadata contains information about the transaction itself
82 | // (can be `null` if not needed)
83 | { what: 'My first BigchainDB transaction' },
84 |
85 | // A transaction needs an output
86 | [ driver.Transaction.makeOutput(
87 | driver.Transaction.makeEd25519Condition(alice.publicKey))
88 | ],
89 | alice.publicKey
90 | )
91 |
92 | // Sign the transaction with private keys
93 | const txSigned = driver.Transaction.signTransaction(tx, alice.privateKey)
94 |
95 | // Or use delegateSignTransaction to provide your own signature function
96 | function signTransaction() {
97 | // get privateKey from somewhere
98 | const privateKeyBuffer = Buffer.from(base58.decode(alice.privateKey))
99 | return function sign(serializedTransaction, input, index) {
100 | const transactionUniqueFulfillment = input.fulfills ? serializedTransaction
101 | .concat(input.fulfills.transaction_id)
102 | .concat(input.fulfills.output_index) : serializedTransaction
103 | const transactionHash = crypto.createHash('sha3-256').update(transactionUniqueFulfillment).digest()
104 | const ed25519Fulfillment = new Ed25519Sha256();
105 | ed25519Fulfillment.sign(transactionHash, privateKeyBuffer);
106 | return ed25519Fulfillment.serializeUri();
107 | };
108 | }
109 | const txSigned = driver.Transaction.delegateSignTransaction(tx, signTransaction())
110 |
111 | // Send the transaction off to BigchainDB
112 | const conn = new driver.Connection(API_PATH)
113 |
114 | conn.postTransactionCommit(txSigned)
115 | .then(retrievedTx => console.log('Transaction', retrievedTx.id, 'successfully posted.'))
116 | ```
117 |
118 | ### Browser usage
119 |
120 | ```html
121 |
122 |
123 |
124 |
125 | BigchainDB boilerplate
126 |
127 |
128 |
129 |
168 |
169 |
170 | Hello BigchainDB
171 | Your transaction id is: processing
172 |
173 |
174 | ```
175 |
176 | ## BigchainDB Documentation
177 |
178 | - [The Hitchhiker's Guide to BigchainDB](https://www.bigchaindb.com/developers/guide/)
179 | - [HTTP API Reference](https://docs.bigchaindb.com/projects/server/en/latest/http-client-server-api.html)
180 | - [The Transaction Model](https://docs.bigchaindb.com/projects/server/en/latest/data-models/transaction-model.html?highlight=crypto%20conditions)
181 | - [Inputs and Outputs](https://docs.bigchaindb.com/projects/server/en/latest/data-models/inputs-outputs.html)
182 | - [Asset Transfer](https://docs.bigchaindb.com/projects/py-driver/en/latest/usage.html#asset-transfer)
183 | - [All BigchainDB Documentation](https://docs.bigchaindb.com/)
184 |
185 | ## Speed Optimizations
186 |
187 | This implementation plays "safe" by using JS-native (or downgradable) libraries for its crypto-related functions to keep compatibilities with the browser. If you do want some more speed, feel free to explore the following:
188 |
189 | * [chloride](https://github.com/dominictarr/chloride), or its underlying [sodium](https://github.com/paixaop/node-sodium) library
190 | * [node-sha3](https://github.com/phusion/node-sha3) -- **MAKE SURE** to use [steakknife's fork](https://github.com/steakknife/node-sha3) if [the FIPS 202 upgrade](https://github.com/phusion/node-sha3/pull/25) hasn't been merged (otherwise, you'll run into all kinds of hashing problems)
191 |
192 | ## Development
193 |
194 | ```js
195 | git clone git@github.com:bigchaindb/js-bigchaindb-driver.git
196 | cd js-bigchaindb-driver/
197 |
198 | npm i
199 | npm run dev
200 | ```
201 |
202 | After updating source files in `src/`, make sure to update the API documentation. The following command will scan all source files and create the Markdown output into `./API.md`:
203 |
204 | ```bash
205 | npm run doc
206 | ```
207 |
208 | ## Release Process
209 |
210 | See the file named [RELEASE_PROCESS.md](RELEASE_PROCESS.md).
211 |
212 | ## Authors
213 |
214 | * inspired by [`js-bigchaindb-quickstart`](https://github.com/sohkai/js-bigchaindb-quickstart) of @sohkhai [thanks]
215 | * BigchainDB
216 | * BigchainDB contributors
217 |
218 | ## Licenses
219 |
220 | See [LICENSE](LICENSE) and [LICENSE-docs](LICENSE-docs).
221 |
--------------------------------------------------------------------------------
/RELEASE_PROCESS.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | # Our Release Process
8 |
9 | ## Notes
10 |
11 | BigchainDB follows
12 | [the Python form of Semantic Versioning](https://packaging.python.org/tutorials/distributing-packages/#choosing-a-versioning-scheme)
13 | (i.e. MAJOR.MINOR.PATCH),
14 | which is almost identical
15 | to [regular semantic versioning](http://semver.org/), but there's no hyphen, e.g.
16 |
17 | - `0.9.0` for a typical final release
18 | - `4.5.2a1` not `4.5.2-a1` for the first Alpha release
19 | - `3.4.5rc2` not `3.4.5-rc2` for Release Candidate 2
20 |
21 | **Note:** For Git tags (which are used to identify releases on GitHub), we append a `v` in front.
22 |
23 | We follow [BEP-1](https://github.com/bigchaindb/BEPs/tree/master/1), which is our variant of C4, the Collective Code Construction Contract, so a release is just a [tagged commit](https://git-scm.com/book/en/v2/Git-Basics-Tagging) on the `master` branch, i.e. a label for a particular Git commit.
24 |
25 | ## Steps
26 |
27 | 1. Make sure you have a recent version of node and npm.
28 | 1. `npm install`
29 | 1. Update all npm package dependencies, where possible. You might have to freeze some versions. Run all tests locally (`npm run test`) and make sure they pass. Make a pull request (to be merged into the `master` branch) and make sure all tests are passing there (in Travis). Merge the pull request.
30 | 1. Make sure your local `master` branch is in sync with GitHub: `git checkout master` and `git pull`
31 | 1. Do a test build:
32 |
33 | `npm run build`
34 |
35 | If that fails, then get it working.
36 | 1. We use the [release-it](https://www.npmjs.com/package/release-it) package (from npm) to automate most of the release. Make sure you have a recent version.
37 | 1. Login to npm using your npm credentials, so you can publish a new [bigchaindb-driver](https://www.npmjs.com/package/bigchaindb-driver) package there. (The npm account must have permission to do so).
38 |
39 | `npm login`
40 |
41 | 1. release-it needs a Github personal access token so it can interact with GitHub on your behalf. To get one, go to:
42 |
43 | [https://github.com/settings/tokens](https://github.com/settings/tokens)
44 |
45 | and then make that token available as an environment variable, e.g.
46 |
47 | `export GITHUB_TOKEN="f941e0..."`
48 |
49 | 1. Do the release:
50 |
51 | - For a patch release, do `npm run release`
52 | - For a minor release, do `npm run release-minor`
53 | - For a major release, do `npm run release-major`
54 |
55 | If your npm account is using two-factor authentication,
56 | you will have to append a one-time password (OTP) like `--npm.otp=123456`.
57 | The above command will automatically do a bunch of things:
58 |
59 | - bump the project version in `package.json`, then git commit and git push it.
60 | - create a new Git tag of the form `v{verson}`, e.g. `v1.2.3`
61 | - create a new [GitHub release](https://github.com/bigchaindb/js-bigchaindb-driver/releases).
62 | - publish a new npm release
63 |
64 | To see all the arguments passed to `release-it`, search for "release" in [package.json](package.json). The arguments are documented in the [release-it GitHub repo](https://github.com/release-it/release-it).
65 |
66 | 1. Make sure everything worked as expected.
67 |
68 | - Was the version number bumped properly in [package.json](package.json)?
69 | - Was a new Git tag created? See the [list of tags](https://github.com/bigchaindb/js-bigchaindb-driver/tags).
70 | - Was a new GitHub release created? See the [list of releases](https://github.com/bigchaindb/js-bigchaindb-driver/releases).
71 | - Was a new npm package published on npm? [Check on npmjs.com](https://www.npmjs.com/package/bigchaindb-driver).
72 |
73 | 1. You can edit the description of the GitHub release to add or remove details.
74 |
75 | If the docs were updated since the last release, [login to readthedocs.org](https://readthedocs.org/accounts/login/) and go to the **BigchainDB JavaScript Driver** project, then:
76 |
77 | 1. Click on "Builds", select "latest" from the drop-down menu, then click the "Build Version:" button.
78 | 1. Wait for the build of "latest" to finish. This can take a few minutes.
79 | 1. Go to Admin --> Advanced Settings
80 | and make sure that "Default branch:" (i.e. what "latest" points to)
81 | is set to the new release's tag, e.g. `v0.9.1`.
82 | (It won't be an option if you didn't wait for the build of "latest" to finish.)
83 | Then scroll to the bottom and click "Save".
84 | 1. Go to Admin --> Versions
85 | and under **Choose Active Versions**, do these things:
86 |
87 | 1. Make sure that the new version's tag is "Active" and "Public"
88 | 1. Make sure the **stable** branch is _not_ active.
89 | 1. Scroll to the bottom of the page and click "Save".
90 |
91 | Congratulations, you have released a new version of the BigchainDB JavaScript Driver!
92 |
--------------------------------------------------------------------------------
/compose/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.6
2 |
3 | RUN apt-get update && apt-get install -y vim
4 |
5 | RUN mkdir -p /usr/src/app
6 | WORKDIR /usr/src/app
7 |
8 | RUN pip install --upgrade pip ipdb ipython
9 |
10 | COPY . /usr/src/app/
11 |
12 | RUN pip install git+https://github.com/bigchaindb/bigchaindb.git
13 |
--------------------------------------------------------------------------------
/compose/tendermint/tmdata/config.toml:
--------------------------------------------------------------------------------
1 | # This is a TOML config file.
2 | # For more information, see https://github.com/toml-lang/toml
3 |
4 | proxy_app = "tcp://bigchaindb:46658"
5 | moniker = "anonymous"
6 | fast_sync = true
7 | db_backend = "leveldb"
8 | log_level = "state:debug,*:error"
9 |
10 | [consensus]
11 | create_empty_blocks = false
12 |
13 | [rpc]
14 | laddr = "tcp://0.0.0.0:46657"
15 |
16 | [p2p]
17 | laddr = "tcp://0.0.0.0:46656"
18 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | # Copyright BigchainDB GmbH and BigchainDB contributors
2 | # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | # Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | version: '2.1'
6 |
7 | services:
8 | mongodb:
9 | image: mongo:3.6
10 | ports:
11 | - "27017"
12 | command: mongod
13 | bigchaindb:
14 | depends_on:
15 | - mongodb
16 | - tendermint
17 | image: bigchaindb/bigchaindb:master
18 | environment:
19 | BIGCHAINDB_DATABASE_HOST: mongodb
20 | BIGCHAINDB_DATABASE_PORT: 27017
21 | BIGCHAINDB_SERVER_BIND: 0.0.0.0:9984
22 | BIGCHAINDB_WSSERVER_HOST: 0.0.0.0
23 | BIGCHAINDB_TENDERMINT_HOST: tendermint
24 | BIGCHAINDB_TENDERMINT_PORT: 26657
25 | ports:
26 | - "9984:9984"
27 | - "9985:9985"
28 | - "26658"
29 | healthcheck:
30 | test: ["CMD", "bash", "-c", "curl http://bigchaindb:9984 && curl http://tendermint:26657/abci_query"]
31 | interval: 3s
32 | timeout: 5s
33 | retries: 3
34 | command: -l DEBUG start
35 | tendermint:
36 | image: tendermint/tendermint:v0.31.5
37 | # volumes:
38 | # - ./tmdata:/tendermint
39 | entrypoint: ''
40 | ports:
41 | - "26656"
42 | - "26657"
43 | command: sh -c "tendermint init && tendermint node --consensus.create_empty_blocks=false --proxy_app=tcp://bigchaindb:26658"
44 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SPHINXPROJ = BigchainDBJavascriptDriver
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | .PHONY: clean
18 | clean:
19 | rm -rf $(BUILDDIR)/*
20 | @echo
21 | @echo "Removed $(BUILDDIR)/html."
22 |
23 | .PHONY: html
24 | html:
25 | $(SPHINXBUILD) -b html $(SOURCEDIR) $(BUILDDIR)/html
26 | @echo
27 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
28 |
29 | # Catch-all target: route all unknown targets to Sphinx using the new
30 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
31 | %: Makefile
32 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
33 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | # BigchainDBJavaScriptDriverDocs
8 | BigchainDB JavaScript Driver Documentation with Sphinx
9 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=python -msphinx
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 | set SPHINXPROJ=BigchainDBJavascriptDriver
13 |
14 | if "%1" == "" goto help
15 |
16 | %SPHINXBUILD% >NUL 2>NUL
17 | if errorlevel 9009 (
18 | echo.
19 | echo.The Sphinx module was not found. Make sure you have Sphinx installed,
20 | echo.then set the SPHINXBUILD environment variable to point to the full
21 | echo.path of the 'sphinx-build' executable. Alternatively you may add the
22 | echo.Sphinx directory to PATH.
23 | echo.
24 | echo.If you don't have Sphinx installed, grab it from
25 | echo.http://sphinx-doc.org/
26 | exit /b 1
27 | )
28 |
29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
30 | goto end
31 |
32 | :help
33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
34 |
35 | :end
36 | popd
37 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | Sphinx~=1.0
2 | recommonmark>=0.4.0
3 | sphinx-rtd-theme>=0.2.4
4 |
--------------------------------------------------------------------------------
/docs/source/.conf.py.swp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigchaindb/js-bigchaindb-driver/17d3a02cb31749aa008061f6f49042059b775512/docs/source/.conf.py.swp
--------------------------------------------------------------------------------
/docs/source/advanced.rst:
--------------------------------------------------------------------------------
1 |
2 | .. Copyright BigchainDB GmbH and BigchainDB contributors
3 | SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4 | Code is Apache-2.0 and docs are CC-BY-4.0
5 |
6 | =================
7 | Advanced Examples
8 | =================
9 |
10 | Crypto Conditions
11 | -----------------
12 |
13 | Let's start with a basic use case example. Alice bought a bicycle for €240.
14 | She will use the bike for a year and will give it to her daughter afterwards.
15 | First, we create an asset registering the bicycle:
16 |
17 | .. code-block:: js
18 |
19 | const txCreateAliceSimple = driver.Transaction.makeCreateTransaction(
20 | {'asset': 'bicycle'},
21 | {'purchase_price': '€240'},
22 | [
23 | driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(alice.publicKey))
24 | ],
25 | alice.publicKey
26 | )
27 |
28 | const txCreateAliceSimpleSigned = driver.Transaction.signTransaction(txCreateAliceSimple, alice.privateKey)
29 |
30 | After a year, she decides it's time to transfer the bicycle to her daughter Carly.
31 | However, Alice wants to maintain the right over the bike so she can possibly sell it. If she would transfer the bicycle to Carly, she won't be able to do this.
32 | So, Alice needs a crypto conditions that defines that she or her daughter can sign the ``TRANSFER`` transaction to a possible buyer.
33 |
34 | We need to define a threshold as well. This defines how many persons have to sign the transaction to ``TRANSFER`` it.
35 | In this case, we define two subconditions with the public keys from Alice and Carly. Next, we set the threshold to **one**.
36 | This means that just one of the subconditions has to sign the transaction to transfer it.
37 | This can be the mother Alice, or Carly herself.
38 |
39 | .. code-block:: js
40 |
41 | // Create condition for Alice and Carly
42 | let subConditionFrom = driver.Transaction.makeEd25519Condition(alice.publicKey, false)
43 | let subConditionTo = driver.Transaction.makeEd25519Condition(carly.publicKey, false)
44 |
45 | // Create condition object with threshold and subconditions
46 | let condition = driver.Transaction.makeThresholdCondition(1, [subConditionFrom, subConditionTo])
47 |
48 | // Generate output with condition added
49 | let output = driver.Transaction.makeOutput(condition)
50 |
51 | // Add Carly to the output.public_keys field so she is the owner
52 | output.public_keys = [carly.publicKey]
53 |
54 | let transaction = driver.Transaction.makeTransferTransaction(
55 | [{ tx: txCreateAliceSimpleSigned, output_index: 0 }],
56 | [output],
57 | {'meta': 'Transfer to new user with conditions'}
58 | );
59 |
60 | // Add alice as previous owner
61 | transaction.inputs[0].owners_before = [alice.publicKey]
62 |
63 | // Because the addition of crypto conditions, the id for the transaction has to be regenerated
64 | delete transaction.id
65 | transaction.id = sha3.sha3_256
66 | .create()
67 | .update(driver.Transaction.serializeTransactionIntoCanonicalString(transaction))
68 | .hex()
69 |
70 | // Alice has to sign this transfer because she is still the owner of the created asset
71 | let signedCryptoConditionTx = driver.Transaction.signTransaction(transaction, alice.privateKey)
72 |
73 | As you can see, we need to generate a new transactionId because we have added crypto conditions.
74 | We do this with the js-sha3 package, you need to install this package through ``npm``:
75 |
76 | ``npm install --save js-sha3``
77 |
78 | Don't forget to import the package in your code:
79 |
80 | .. code-block:: js
81 |
82 | import * as sha3 from 'js-sha3'
83 |
84 |
85 | If you would like to see a more complex example, please have a look [here](https://github.com/bigchaindb/project-jannowitz/blob/code-examples/js-examples/crypto-conditions.js)
86 |
87 | .. TODO: Document Utils when finished
88 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # Copyright BigchainDB GmbH and BigchainDB contributors
3 | # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4 | # Code is Apache-2.0 and docs are CC-BY-4.0
5 |
6 | #
7 | # BigchainDB Javascript Driver documentation build configuration file, created by
8 | # sphinx-quickstart on Wed Aug 2 15:39:03 2017.
9 | #
10 | # This file is execfile()d with the current directory set to its
11 | # containing dir.
12 | #
13 | # Note that not all possible configuration values are present in this
14 | # autogenerated file.
15 | #
16 | # All configuration values have a default; values that are commented out
17 | # serve to show the default.
18 |
19 | # If extensions (or modules to document with autodoc) are in another directory,
20 | # add these directories to sys.path here. If the directory is relative to the
21 | # documentation root, use os.path.abspath to make it absolute, like shown here.
22 | #
23 | # import os
24 | # import sys
25 | # sys.path.insert(0, os.path.abspath('.'))
26 |
27 |
28 |
29 | # -- General configuration ------------------------------------------------
30 |
31 | # If your documentation needs a minimal Sphinx version, state it here.
32 | #
33 | # needs_sphinx = '1.0'
34 |
35 | import datetime
36 | import sphinx_rtd_theme
37 |
38 | from recommonmark.parser import CommonMarkParser
39 |
40 | # Add any Sphinx extension module names here, as strings. They can be
41 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
42 | # ones.
43 | extensions = [
44 | 'sphinx.ext.autodoc',
45 | ]
46 |
47 | # Add any paths that contain templates here, relative to this directory.
48 | templates_path = ['ntemplates']
49 |
50 | source_parsers = {
51 | '.md': CommonMarkParser,
52 | }
53 |
54 | # The suffix(es) of source filenames.
55 | # You can specify multiple suffix as a list of string:
56 | #
57 | # source_suffix = ['.rst', '.md']
58 | source_suffix = ['.rst', '.md']
59 |
60 | # The master toctree document.
61 | master_doc = 'index'
62 |
63 | # General information about the project.
64 | project = 'BigchainDB Javascript Driver'
65 | now = datetime.datetime.now()
66 | copyright = str(now.year) + ', BigchainDB Contributors'
67 | author = 'BigchainDB Contributors'
68 |
69 | # The version info for the project you're documenting, acts as replacement for
70 | # |version| and |release|, also used in various other places throughout the
71 | # built documents.
72 | #
73 | # The short X.Y version.
74 | version = '0.0.1'
75 | # The full version, including alpha/beta/rc tags.
76 | release = '0.0.1'
77 |
78 | # The language for content autogenerated by Sphinx. Refer to documentation
79 | # for a list of supported languages.
80 | #
81 | # This is also used if you do content translation via gettext catalogs.
82 | # Usually you set "language" from the command line for these cases.
83 | language = None
84 |
85 | # List of patterns, relative to source directory, that match files and
86 | # directories to ignore when looking for source files.
87 | # This patterns also effect to html_static_path and html_extra_path
88 | exclude_patterns = []
89 |
90 | # The name of the Pygments (syntax highlighting) style to use.
91 | pygments_style = 'sphinx'
92 |
93 | # If true, `todo` and `todoList` produce output, else they produce nothing.
94 | todo_include_todos = False
95 |
96 |
97 | # -- Options for HTML output ----------------------------------------------
98 |
99 | # The theme to use for HTML and HTML Help pages. See the documentation for
100 | # a list of builtin themes.
101 | #
102 | html_theme = 'sphinx_rtd_theme'
103 |
104 | # Theme options are theme-specific and customize the look and feel of a theme
105 | # further. For a list of options available for each theme, see the
106 | # documentation.
107 | #
108 | # html_theme_options = {}
109 |
110 | # Add any paths that contain custom static files (such as style sheets) here,
111 | # relative to this directory. They are copied after the builtin static files,
112 | # so a file named "default.css" will overwrite the builtin "default.css".
113 | # html_static_path = ['nstatic']
114 | # Commented out this option because Sphinx can not find the path
115 |
116 | # Custom sidebar templates, must be a dictionary that maps document names
117 | # to template names.
118 | #
119 | # This is required for the alabaster theme
120 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
121 | html_sidebars = {
122 | '**': [
123 | 'about.html',
124 | 'navigation.html',
125 | 'relations.html', # needs 'show_related': True theme option to display
126 | 'searchbox.html',
127 | 'donate.html',
128 | ]
129 | }
130 |
131 |
132 | # -- Options for HTMLHelp output ------------------------------------------
133 |
134 | # Output file base name for HTML help builder.
135 | htmlhelp_basename = 'BigchainDBJavascriptDriverdoc'
136 |
137 |
138 | # -- Options for LaTeX output ---------------------------------------------
139 |
140 | latex_elements = {
141 | # The paper size ('letterpaper' or 'a4paper').
142 | #
143 | # 'papersize': 'letterpaper',
144 |
145 | # The font size ('10pt', '11pt' or '12pt').
146 | #
147 | # 'pointsize': '10pt',
148 |
149 | # Additional stuff for the LaTeX preamble.
150 | #
151 | # 'preamble': '',
152 |
153 | # Latex figure (float) alignment
154 | #
155 | # 'figure_align': 'htbp',
156 | }
157 |
158 | # Grouping the document tree into LaTeX files. List of tuples
159 | # (source start file, target name, title,
160 | # author, documentclass [howto, manual, or own class]).
161 | latex_documents = [
162 | (master_doc, 'BigchainDBJavascriptDriver.tex', 'BigchainDB Javascript Driver Documentation',
163 | 'BigchainDB', 'manual'),
164 | ]
165 |
166 |
167 | # -- Options for manual page output ---------------------------------------
168 |
169 | # One entry per manual page. List of tuples
170 | # (source start file, name, description, authors, manual section).
171 | man_pages = [
172 | (master_doc, 'bigchaindbjavascriptdriver', 'BigchainDB Javascript Driver Documentation',
173 | [author], 1)
174 | ]
175 |
176 |
177 | # -- Options for Texinfo output -------------------------------------------
178 |
179 | # Grouping the document tree into Texinfo files. List of tuples
180 | # (source start file, target name, title, author,
181 | # dir menu entry, description, category)
182 | texinfo_documents = [
183 | (master_doc, 'BigchainDBJavascriptDriver', 'BigchainDB Javascript Driver Documentation',
184 | author, 'BigchainDBJavascriptDriver', 'One line description of project.',
185 | 'Miscellaneous'),
186 | ]
187 |
188 |
189 |
190 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 |
2 | .. Copyright BigchainDB GmbH and BigchainDB contributors
3 | SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4 | Code is Apache-2.0 and docs are CC-BY-4.0
5 |
6 | BigchainDB Javascript Driver Documentation
7 | ==========================================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 |
12 | ← Back to All BigchainDB Docs
13 | readme
14 | quickstart
15 | usage
16 | advanced
17 |
18 | Indices and tables
19 | ==================
20 |
21 | * :ref:`genindex`
22 | * :ref:`modindex`
23 | * :ref:`search`
24 |
--------------------------------------------------------------------------------
/docs/source/quickstart.rst:
--------------------------------------------------------------------------------
1 |
2 | .. Copyright BigchainDB GmbH and BigchainDB contributors
3 | SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4 | Code is Apache-2.0 and docs are CC-BY-4.0
5 |
6 | =========================
7 | Quickstart / Installation
8 | =========================
9 |
10 | Installation with package manager npm:
11 |
12 | .. code-block:: bash
13 |
14 | $ npm install bigchaindb-driver
15 |
--------------------------------------------------------------------------------
/docs/source/readme.rst:
--------------------------------------------------------------------------------
1 |
2 | .. Copyright BigchainDB GmbH and BigchainDB contributors
3 | SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4 | Code is Apache-2.0 and docs are CC-BY-4.0
5 |
6 | BigchainDB JavaScript Driver
7 | ============================
8 |
9 | .. image:: https://img.shields.io/npm/v/bigchaindb-driver.svg
10 | :target: https://www.npmjs.com/package/bigchaindb-driver
11 |
12 | .. image:: https://codecov.io/gh/bigchaindb/js-bigchaindb-driver/branch/master/graph/badge.svg
13 | :target: https://codecov.io/gh/bigchaindb/js-bigchaindb-driver
14 |
15 | .. image:: https://img.shields.io/badge/js-ascribe-39BA91.svg
16 | :target: https://github.com/ascribe/javascript
17 |
18 | .. image:: https://travis-ci.com/bigchaindb/js-bigchaindb-driver.svg?branch=master
19 | :target: https://travis-ci.com/bigchaindb/js-bigchaindb-driver
20 |
21 | .. image:: https://badges.greenkeeper.io/bigchaindb/js-bigchaindb-driver.svg
22 | :target: https://greenkeeper.io/
23 |
24 | Features
25 | --------
26 |
27 | * Support for preparing, fulfilling, and sending transactions to a BigchainDB
28 | node.
29 | * Retrieval of transactions by id.
30 | * Getting status of a transaction by id.
31 |
32 | Compatibility Matrix
33 | --------------------
34 |
35 | +-----------------------+----------------------------------+
36 | | **BigchainDB Server** | **BigchainDB Javascript Driver** |
37 | +=======================+==================================+
38 | | ``0.10`` | ``0.1.x`` |
39 | +-----------------------+----------------------------------+
40 | | ``1.0`` | ``0.3.x`` |
41 | +-----------------------+----------------------------------+
42 | | ``1.3`` | ``3.x.x`` |
43 | +-----------------------+----------------------------------+
44 | | ``2.0`` | ``4.x.x`` |
45 | +-----------------------+----------------------------------+
46 |
47 |
48 |
49 | Older versions
50 | --------------------
51 |
52 | **Version 4.x.x**
53 |
54 | As part of the changes in the BigchainDB 2.0 server, some endpoints were
55 | modified. In order to be consistent with them, the JS driver does not have
56 | anymore the `pollStatusAndFetchTransaction()` method as there are three
57 | different ways of posting a transaction:
58 |
59 | - `commit` using the `postTransaction` or the `postTransactionCommit`: the response will return after the transaction is committed to a block.
60 | - `sync` using the `postTransactionSync`: the response will return after the transaction is validated.
61 | - `async` using the `postTransactionAsync`: the response will return immediately and not wait to see if the transaction is valid.
62 |
63 | By default in the docs we will use the `postTransactionCommit` as is way of
64 | being sure that the transaction is validated and commited to a block, so
65 | there will not be any issue if you try to do any other action with the asset immediately.
66 |
67 | Note: In order to not create breaking changes, both methods `postTransaction` and `postTransactionCommit` are kept although
68 | they do exactly the same
69 |
70 |
71 | **Version 3.2.x**
72 |
73 | For versions below 3.2, a transfer transaction looked like:
74 |
75 | .. code-block:: js
76 |
77 | const createTranfer = BigchainDB.Transaction.makeTransferTransaction(
78 | txCreated,
79 | metadata, [BigchainDB.Transaction.makeOutput(
80 | BigchainDB.Transaction.makeEd25519Condition(alice.publicKey))],
81 | 0
82 | )
83 |
84 | const signedTransfer = BigchainDB.Transaction.signTransaction(createTranfer,
85 | keypair.privateKey)
86 |
87 |
88 | In order to upgrade and do it compatible with the new driver version, this
89 | transaction should be now:
90 |
91 | .. code-block:: js
92 |
93 | const createTranfer = BigchainDB.Transaction.makeTransferTransaction(
94 | [{ tx: txCreated, output_index: 0 }],
95 | [BigchainDB.Transaction.makeOutput(
96 | BigchainDB.Transaction.makeEd25519Condition(alice.publicKey))],
97 | metaData
98 | )
99 |
100 | const signedTransfer = BigchainDB.Transaction.signTransaction(createTranfer,
101 | keypair.privateKey)
102 |
103 |
104 | The upgrade allows to create transfer transaction spending outputs that belong
105 | to different transactions. So for instance is now possible to create a transfer
106 | transaction spending two outputs from two different create transactions:
107 |
108 |
109 | .. code-block:: js
110 |
111 | const createTranfer = BigchainDB.Transaction.makeTransferTransaction(
112 | [{ tx: txCreated1, output_index: 0 },
113 | { tx: txCreated2, output_index: 0}],
114 | [BigchainDB.Transaction.makeOutput(
115 | BigchainDB.Transaction.makeEd25519Condition(alice.publicKey))],
116 | metaData
117 | )
118 |
119 | const signedTransfer = BigchainDB.Transaction.signTransaction(createTranfer,
120 | keypair.privateKey)
121 |
--------------------------------------------------------------------------------
/docs/upgrade-guides/0.3.0.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | # Updating js-bigchaindb-driver from v0.1.x to v0.3.0
8 |
9 | The latest version of js-bigchaindb-driver contains breaking changes to its
10 | external API. In this document, we enumerate all changes to allow you to make
11 | upgrades efficiently.
12 |
13 | Note that upgrading the js-bigchaindb-driver to v0.3.0 was done to enable
14 | functionality included in the latest (v1.0) BigchainDB release. A full list of
15 | BigchainDB v1.0's breaking changes can be found
16 | [here](https://github.com/bigchaindb/bigchaindb/blob/17913dca682ff105540c0ea73365f1763efc2083/docs/upgrade-guides/v0.10--%3Ev1.0.md).
17 | Note that v1.0 [contains breaking changes to its core data
18 | models](https://github.com/bigchaindb/bigchaindb/blob/17913dca682ff105540c0ea73365f1763efc2083/docs/upgrade-guides/v0.10--%3Ev1.0.md#breaking-changes-to-the-data-model).
19 |
20 | This document will just go into the very specific breaking changes affecting
21 | the JavaScript driver.
22 |
23 |
24 | ### Breaking changes to js-bigchaindb-driver's APIs
25 |
26 | #### Output amount is now a string
27 |
28 | ```js
29 | // old
30 | export default function makeOutput(condition, amount = 1) {}
31 |
32 | // new
33 | export default function makeOutput(condition, amount = '1') {}
34 | ```
35 |
36 |
37 | #### Update to Crypto-Conditions version 2
38 |
39 | All conditions or fulfillments passed manually to the driver now need to comply
40 | with ILP's Crypto-Condition version 2 specification. For more information,
41 | [see the updated
42 | specification](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02)
43 | or checkout the [latest reference implementation of Crypto-Conditions in
44 | JavaScript](https://github.com/interledgerjs/five-bells-condition).
45 |
46 |
47 | #### Several `Connection` methods now require positional arguments
48 |
49 | ##### `Connection.listBlocks`
50 |
51 | ```js
52 | // old
53 | new Connection(PATH).listBlocks({ tx_id, status })
54 |
55 | // new
56 | new Connection(PATH).listBlocks(transactionId, status)
57 | ```
58 |
59 |
60 | ##### `Connection.listOutputs`
61 |
62 | ```js
63 | // old
64 | new Connection(PATH).listOutputs({ public_key, unspent })
65 |
66 | // new
67 | new Connection(PATH).listOutputs(publicKey, spent)
68 | ```
69 |
70 | **NOTE:** The `unspent` flag has been inversed. This is inline [with breaking
71 | changes to BigchainDB
72 | v1.0](https://github.com/bigchaindb/bigchaindb/blob/17913dca682ff105540c0ea73365f1763efc2083/docs/upgrade-guides/v0.10--%3Ev1.0.md#get-apiv1outputs).
73 |
74 |
75 | ##### `Connection.listTransactions`
76 |
77 | ```js
78 | // old
79 | new Connection(PATH).listTransactions({ asset_id, operation })
80 |
81 | // new
82 | new Connection(PATH).listTransactions(assetId, operation)
83 | ```
84 |
85 |
86 | ### Newly added endpoints
87 |
88 | ##### `Connection.searchAsset`
89 |
90 | ```js
91 | // new
92 | new Connection(PATH).searchAssets(search)
93 | ```
94 |
95 | A querying interface to text-search all assets in BigchainDB. For more
96 | documentation, [see BigchainDB's HTTP
97 | API](https://docs.bigchaindb.com/projects/server/en/latest/http-client-server-api.html#assets).
98 |
99 |
100 | ### Newly available bundles and CDN hosting
101 |
102 | The driver is now bundled automatically each time we publish it to npm.com. We
103 | now ship packages for `commonjs`, `commonjs2`, `amd`, `umd`, `window` and
104 | node.js. Thanks to unpkg.com, we're also able to provide all these packages on
105 | a CDN. A link to all the bundles can be found
106 | [here](https://unpkg.com/bigchaindb-driver@0.3.0/dist/browser/).
107 |
108 |
109 | A few notes:
110 |
111 | - Adjust version number in link as appropriate
112 | - only include `bigchaindb-driver.*.min.js`, but now everything `bundle.*`.
113 | This is [a known
114 | issue](https://github.com/bigchaindb/js-bigchaindb-driver/issues/66).
115 |
--------------------------------------------------------------------------------
/examples/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [["@babel/preset-env"]],
3 | "plugins": [
4 | "@babel/plugin-syntax-async-generators",
5 | [
6 | "@babel/plugin-transform-runtime",
7 | {
8 | "absoluteRuntime": false,
9 | "helpers": true,
10 | "regenerator": true
11 | }
12 | ],
13 | "@babel/plugin-transform-regenerator",
14 | "@babel/plugin-transform-async-to-generator"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/examples/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 |
6 |
7 | # Quick Notes
8 | `dotenv` is listed as a dependencies in `package.json`.
9 | If you want to use this, add a `.env` file to the root of this project (same level as this `README.md` file)
10 | and replace the variables to fit your specific config.
11 |
12 | ```
13 | BIGCHAINDB_API_PATH=https://test.bigchaindb.com/api/v1/
14 | BIGCHAINDB_APP_ID=
15 | BIGCHAINDB_APP_KEY=
16 | ```
17 |
18 | # Usage
19 | `npm install` -> Installs all required dependencies to run these examples.
20 |
21 | ## Different Examples
22 | **Basic Usage**: Create asset and transfer it to new owner.
23 | -> `npm start`
24 |
25 | **Async/Await Basic Usage**: Basic usage example rewritten with async/await.
26 | -> `npm run basic-async`
27 |
28 | **Querying for Assets**: Query for assetdata or metadata.
29 | -> `npm run query-assets`
30 |
31 | **Seed/Keypair Functionality**: Create keypair with bip39 library.
32 | -> `npm run seed-func`
33 |
--------------------------------------------------------------------------------
/examples/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-driver-bigchaindb-examples",
3 | "version": "1.0.0",
4 | "main": "src/basic-usage.js",
5 | "scripts": {
6 | "build": "npm run clean && babel src -d dist",
7 | "serve": "node dist/basic-usage.js",
8 | "clean": "rimraf ./dist",
9 | "start": "nodemon src/basic-usage.js --exec babel-node",
10 | "query-assets": "nodemon src/query-assets.js --exec babel-node",
11 | "seed-func": "nodemon src/seed-func.js --exec babel-node",
12 | "basic-async": "nodemon src/basic-usage-async-await.js --exec babel-node"
13 | },
14 | "author": "BigchainDB",
15 | "license": "MIT",
16 | "devDependencies": {
17 | "@babel/cli": "^7.13.0",
18 | "@babel/core": "^7.13.8",
19 | "@babel/eslint-parser": "^7.13.8",
20 | "@babel/node": "7.13.0",
21 | "@babel/plugin-syntax-async-generators": "^7.8.4",
22 | "@babel/plugin-transform-async-to-generator": "^7.13.0",
23 | "@babel/plugin-transform-regenerator": "^7.12.13",
24 | "@babel/plugin-transform-runtime": "^7.13.9",
25 | "@babel/preset-env": "^7.13.9",
26 | "@babel/register": "^7.13.8",
27 | "babel-loader": "^8.2.2",
28 | "nodemon": "^2.0.7",
29 | "rimraf": "^3.0.2"
30 | },
31 | "repository": "/",
32 | "private": true,
33 | "dependencies": {
34 | "bigchaindb-driver": "^4.1.2",
35 | "bip39": "^3.0.3",
36 | "dotenv": "^8.2.0"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/examples/src/basic-usage-async-await.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable import/no-unresolved */
6 |
7 | const driver = require('bigchaindb-driver')
8 | require('dotenv').config()
9 |
10 | // ======== Preparation ======== //
11 | const conn = new driver.Connection('https://test.ipdb.io/api/v1/', {
12 | header1: 'header1_value',
13 | header2: 'header2_value'
14 | })
15 |
16 | const alice = new driver.Ed25519Keypair()
17 | const bob = new driver.Ed25519Keypair()
18 |
19 | const assetdata = {
20 | 'bicycle': {
21 | 'serial_number': 'abcd1234',
22 | 'manufacturer': 'Bicycle Inc.',
23 | }
24 | }
25 |
26 | const metadata = { 'planet': 'earth' }
27 |
28 | // Call async basic usage function
29 | basicUsage()
30 |
31 | async function basicUsage() {
32 | // ======== Create Transaction Bicycle ======== //
33 | const txCreateAliceSimple = driver.Transaction.makeCreateTransaction(
34 | assetdata,
35 | metadata,
36 | [
37 | driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(alice.publicKey))
38 | ],
39 | alice.publicKey
40 | )
41 |
42 | const txCreateAliceSimpleSigned =
43 | driver.Transaction.signTransaction(txCreateAliceSimple, alice.privateKey)
44 |
45 | // ======== POST CREATE Transaction ======== //
46 | const createdTx = await conn.postTransactionCommit(txCreateAliceSimpleSigned)
47 |
48 | // ======== POST TRANSFER Transaction ======== //
49 | const txTransferBob = driver.Transaction.makeTransferTransaction(
50 | [{ tx: createdTx, output_index: 0 }],
51 | [driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
52 | { price: '100 euro' }
53 | )
54 |
55 | const txTransferBobSigned = driver.Transaction.signTransaction(txTransferBob, alice.privateKey)
56 |
57 | await conn.postTransactionCommit(txTransferBobSigned)
58 |
59 | // ======== Querying Assets ======== //
60 | const assets = await conn.searchAssets('Bicycle Inc.')
61 | console.log(assets) // eslint-disable-line no-console
62 | }
63 |
--------------------------------------------------------------------------------
/examples/src/basic-usage.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable import/no-unresolved */
6 |
7 | const driver = require('bigchaindb-driver')
8 | require('dotenv').config()
9 |
10 | // ======== Preparation ======== //
11 | const conn = new driver.Connection('https://test.ipdb.io/api/v1/', {
12 | header1: 'header1_value',
13 | header2: 'header2_value'
14 | })
15 |
16 | const alice = new driver.Ed25519Keypair()
17 | const bob = new driver.Ed25519Keypair()
18 |
19 | const assetdata = {
20 | 'bicycle': {
21 | 'serial_number': 'abcd1234',
22 | 'manufacturer': 'Bicycle Inc.',
23 | }
24 | }
25 |
26 | const metadata = { 'planet': 'earth' }
27 |
28 | // ======== Create Transaction Bicycle ======== //
29 | const txCreateAliceSimple = driver.Transaction.makeCreateTransaction(
30 | assetdata,
31 | metadata,
32 | [
33 | driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(alice.publicKey))
34 | ],
35 | alice.publicKey
36 | )
37 |
38 | const txCreateAliceSimpleSigned =
39 | driver.Transaction.signTransaction(txCreateAliceSimple, alice.privateKey)
40 |
41 | // ======== Post Transaction and Fetch Result ======== //
42 | conn.postTransactionCommit(txCreateAliceSimpleSigned)
43 | // ======== Transfer Bicycle to Bob ======== //
44 | .then((fetchedTx) => {
45 | const txTransferBob = driver.Transaction.makeTransferTransaction(
46 | [{ tx: fetchedTx, output_index: 0 }],
47 | [driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
48 | { price: '100 euro' }
49 | )
50 |
51 | // Sign transfer transaction with Alice's private key
52 | const txTransferBobSigned = driver.Transaction.signTransaction(txTransferBob, alice.privateKey)
53 |
54 | return conn.postTransactionCommit(txTransferBobSigned)
55 | })
56 | .then(tx => {
57 | console.log('Is Bob the owner?', tx.outputs[0].public_keys[0] === bob.publicKey) // eslint-disable-line no-console
58 | console.log('Was Alice the previous owner?', tx.inputs[0].owners_before[0] === alice.publicKey) // eslint-disable-line no-console
59 | })
60 |
61 | // ======== Search Asset by Serial Number ======== //
62 | .then(() => conn.searchAssets('Bicycle Inc.'))
63 | .then(assets => console.log('Found assets with serial number Bicycle Inc.:', assets)) // eslint-disable-line no-console
64 |
--------------------------------------------------------------------------------
/examples/src/query-assets.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable import/no-unresolved */
6 |
7 | const driver = require('bigchaindb-driver')
8 | require('dotenv').config()
9 |
10 | // ======== Preparation ======== //
11 | const conn = new driver.Connection('https://example.com/api/v1/', {
12 | header1: 'header1_value',
13 | header2: 'header2_value'
14 | })
15 |
16 | const alice = new driver.Ed25519Keypair()
17 |
18 | // ======== Asset Array ======== //
19 | const assetArray = []
20 | assetArray.push({ 'bicycle': { 'serial_number': 'abc', 'manufacturer': 'BicyclesInc' } })
21 | assetArray.push({ 'bicycle': { 'serial_number': 'cde', 'manufacturer': 'BicyclesInc' } })
22 | assetArray.push({ 'bicycle': { 'serial_number': 'fgh', 'manufacturer': 'BicyclesInc' } })
23 |
24 | const metadata = { 'planet': 'Pluto' }
25 |
26 | // ======== Create Transactions for bicycles ======== //
27 | function createTx(assetdata) {
28 | const txCreate = driver.Transaction.makeCreateTransaction(
29 | assetdata,
30 | metadata,
31 | [
32 | driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(alice.publicKey))
33 | ],
34 | alice.publicKey
35 | )
36 |
37 | const txCreateSigned = driver.Transaction.signTransaction(txCreate, alice.privateKey)
38 | return conn.postTransactionCommit(txCreateSigned)
39 | }
40 |
41 | // ======== Execute all promises in order to post transactions and fetch them ======== //
42 | Promise.all(assetArray.map(createTx))
43 |
44 | // ======== Querying Assets for Assetdata ======== //
45 | .then(() => conn.searchAssets('BicyclesInc'))
46 | .then(assets => console.log('Found assets with serial number "BicyclesInc":', assets)) // eslint-disable-line no-console
47 |
48 | // ======== Querying Assets for Metadata ======== //
49 | .then(() => conn.searchMetadata('Pluto'))
50 | .then(assets => console.log('Found assets with metadata "Pluto":', assets)) // eslint-disable-line no-console
51 |
--------------------------------------------------------------------------------
/examples/src/seed-func.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable import/no-unresolved */
6 |
7 | import bip39 from 'bip39'
8 |
9 | const driver = require('bigchaindb-driver')
10 |
11 | // ======== Create Keypair ======== //
12 | /**
13 | * Use a passphrase to derive a keypair
14 | * If you use the same seed -> you will derive the same keypair
15 | *
16 | * mnemnoicToSeed() transforms the passphrase you gave as an input
17 | * to a byteArray
18 | *
19 | * BigchainDB however only accepts an input length of 32 characters
20 | * so we have to slice this to give it as input for driver.Ed25519Keypair()
21 | *
22 | * Is it safe to slice? Yes, a seed of length 32 is very safe according
23 | * to related papers discussing this.
24 | */
25 | const passphrase = 'This is a random passphrase'
26 | const seed = bip39.mnemonicToSeed(passphrase).slice(0, 32)
27 |
28 | const keypair = new driver.Ed25519Keypair(seed)
29 |
30 | console.log(`Public Key: ${keypair.publicKey} - Private Key: ${keypair.privateKey}`) // eslint-disable-line no-console
31 |
32 | // ======== Other Bip39 Functionality not related to BigchainDB ======== //
33 |
34 | /* Create Random passphrase */
35 | const mnemonic = bip39.generateMnemonic()
36 | console.log('Random passphrase: ', mnemonic) // eslint-disable-line no-console
37 |
38 | /* Validate mnemnoic */
39 | console.log(bip39.validateMnemonic(mnemonic)) // eslint-disable-line no-console
40 | console.log(bip39.validateMnemonic('some random strings together but to short')) // eslint-disable-line no-console
41 |
--------------------------------------------------------------------------------
/media/repo-banner.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigchaindb/js-bigchaindb-driver/17d3a02cb31749aa008061f6f49042059b775512/media/repo-banner.sketch
--------------------------------------------------------------------------------
/media/repo-banner@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bigchaindb/js-bigchaindb-driver/17d3a02cb31749aa008061f6f49042059b775512/media/repo-banner@2x.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bigchaindb-driver",
3 | "version": "4.3.0",
4 | "description": "Node.js driver for BigchainDB",
5 | "homepage": "https://www.bigchaindb.com/",
6 | "bugs": "https://github.com/bigchaindb/js-bigchaindb-driver/issues",
7 | "repository": {
8 | "type": "git",
9 | "url": "git+https://github.com/bigchaindb/js-bigchaindb-driver.git"
10 | },
11 | "license": "Apache-2.0",
12 | "author": "BigchainDB",
13 | "files": [
14 | "dist",
15 | "types"
16 | ],
17 | "main": "./dist/node/index.js",
18 | "browser": "./dist/browser/bigchaindb-driver.cjs2.min.js",
19 | "types": "./types/index.d.ts",
20 | "sideEffects": false,
21 | "scripts": {
22 | "lint": "eslint .",
23 | "lint:fix": "eslint . --fix",
24 | "build": "npm run clean && npm run build:cjs && npm run build:dist",
25 | "build:bundle": "webpack",
26 | "build:cjs": "cross-env BABEL_ENV=cjs babel ./src -d dist/node",
27 | "build:dist": "cross-env NODE_ENV=production webpack",
28 | "dev": "webpack -w",
29 | "clean": "rimraf dist/bundle dist/browser dist/node",
30 | "test": "npm run lint && nyc ava && npm run report-coverage",
31 | "thanks": "cowsay Hi, thanks for your interest in BigchainDB. We appreciate your contribution!",
32 | "release": "read -p 'GITHUB_TOKEN: ' GITHUB_TOKEN && export GITHUB_TOKEN=$GITHUB_TOKEN && release-it --src.tagName='v%s'",
33 | "release-minor": "release-it minor --non-interactive",
34 | "release-major": "release-it major --non-interactive",
35 | "prepublishOnly": "npm run build",
36 | "report-coverage": "nyc report --reporter=lcov > coverage.lcov && codecov",
37 | "doc": "documentation build src/index.js -f md -o API.md -g --markdown-toc"
38 | },
39 | "devDependencies": {
40 | "@ava/babel": "^2.0.0",
41 | "@babel/cli": "^7.17.0",
42 | "@babel/core": "^7.17.2",
43 | "@babel/eslint-parser": "^7.17.0",
44 | "@babel/plugin-proposal-export-default-from": "^7.16.7",
45 | "@babel/plugin-proposal-object-rest-spread": "^7.16.7",
46 | "@babel/plugin-syntax-async-generators": "^7.8.4",
47 | "@babel/plugin-transform-async-to-generator": "^7.16.8",
48 | "@babel/plugin-transform-object-assign": "^7.16.7",
49 | "@babel/plugin-transform-regenerator": "^7.16.7",
50 | "@babel/plugin-transform-runtime": "^7.17.0",
51 | "@babel/preset-env": "^7.16.11",
52 | "@babel/register": "^7.17.0",
53 | "ava": "^3.15.0",
54 | "babel-loader": "^8.2.2",
55 | "buffer": "^6.0.3",
56 | "codecov": "^3.8.1",
57 | "cross-env": "^7.0.3",
58 | "documentation": "^13.2.5",
59 | "eslint": "^8.9.0",
60 | "eslint-config-airbnb-base": "^15.0.0",
61 | "eslint-plugin-import": "^2.25.4",
62 | "husky": "^7.0.4",
63 | "lint-staged": "^12.3.4",
64 | "nyc": "^15.1.0",
65 | "release-it": "^14.12.4",
66 | "rewire": "^6.0.0",
67 | "rimraf": "^3.0.2",
68 | "sinon": "^13.0.1",
69 | "terser-webpack-plugin": "^5.3.1",
70 | "webpack": "^5.68.0",
71 | "webpack-cli": "^4.9.2",
72 | "webpack-merge": "^5.8.0",
73 | "webpack-sources": "^3.2.3"
74 | },
75 | "dependencies": {
76 | "@babel/runtime-corejs3": "^7.17.2",
77 | "abort-controller": "^3.0.0",
78 | "bs58": "^4.0.1",
79 | "clone": "^2.1.2",
80 | "core-js": "^3.21.0",
81 | "crypto-conditions": "2.2.1",
82 | "decamelize": "^5.0.0",
83 | "es6-promise": "^4.2.8",
84 | "fetch-ponyfill": "^7.1.0",
85 | "js-sha3": "^0.8.0",
86 | "json-stable-stringify": "^1.0.1",
87 | "query-string": "^7.1.1",
88 | "sprintf-js": "^1.1.2",
89 | "tweetnacl": "^1.0.3"
90 | },
91 | "keywords": [
92 | "bigchaindb",
93 | "driver",
94 | "blockchain",
95 | "decentralized",
96 | "dapp"
97 | ],
98 | "lint-staged": {
99 | "*.js": [
100 | "eslint"
101 | ]
102 | },
103 | "ava": {
104 | "files": [
105 | "test/**/*.js",
106 | "!test/constants.js"
107 | ],
108 | "source": [
109 | "**/*.{js,jsx}",
110 | "!node_modules/**/*",
111 | "!dist/**/*"
112 | ],
113 | "failFast": true,
114 | "failWithoutAssertions": false,
115 | "tap": true,
116 | "powerAssert": false,
117 | "require": [
118 | "@babel/register"
119 | ],
120 | "babel": true
121 | },
122 | "husky": {
123 | "hooks": {
124 | "pre-commit": "lint-staged"
125 | }
126 | },
127 | "release-it": {
128 | "github": {
129 | "release": true
130 | },
131 | "git": {
132 | "tagName": "v${version}"
133 | },
134 | "hooks": {
135 | "before:init": [
136 | "npm run test"
137 | ]
138 | },
139 | "npm": {
140 | "publish": true
141 | }
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/plugins/add-vendors-plugin.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable strict, no-console, object-shorthand, import/no-extraneous-dependencies */
6 |
7 | const { ConcatSource } = require('webpack-sources')
8 |
9 | module.exports = class AddVendorsPlugin {
10 | constructor(base) {
11 | this.base = base
12 | }
13 |
14 | apply(compiler) {
15 | compiler.hooks.emit.tapAsync(
16 | `AddVendorsPlugin ${this.base}`,
17 | (compilation, callback) => {
18 | const main = compilation.assets[`main.${this.base}`]
19 | const mainMap = compilation.assets[`main.${this.base}.map`]
20 | const vendor = compilation.assets[`vendors.${this.base}`]
21 |
22 | if (main && vendor) {
23 | const compiledAsset = new ConcatSource(main._value[0])
24 | compiledAsset.add(vendor)
25 | compiledAsset.add(main._value[1])
26 | compilation.assets = {}
27 | compilation.assets[this.base] = compiledAsset
28 | } else if (main && mainMap) {
29 | compilation.assets = {}
30 | compilation.assets[this.base] = main
31 | compilation.assets[`${this.base}.map`] = mainMap
32 | }
33 |
34 | callback()
35 | }
36 | )
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Ed25519Keypair.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import base58 from 'bs58'
6 | import { sign } from 'tweetnacl'
7 |
8 | /**
9 | * @public
10 | * Ed25519 keypair in base58 (as BigchainDB expects base58 keys)
11 | * @type {Object}
12 | * @param {Buffer} [seed] A seed that will be used as a key derivation function
13 | * @property {string} publicKey
14 | * @property {string} privateKey
15 | */
16 | export default function Ed25519Keypair(seed) {
17 | const keyPair = seed ? sign.keyPair.fromSeed(seed) : sign.keyPair()
18 | this.publicKey = base58.encode(Buffer.from(keyPair.publicKey))
19 | // tweetnacl's generated secret key is the secret key + public key (resulting in a 64-byte buffer)
20 | this.privateKey = base58.encode(Buffer.from(keyPair.secretKey.slice(0, 32)))
21 | }
22 |
--------------------------------------------------------------------------------
/src/baseRequest.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | // TODO: remove abort-controller when using Node >=15
6 | import AbortController from 'abort-controller'
7 | import { Promise } from 'es6-promise'
8 | import fetchPonyfill from 'fetch-ponyfill'
9 | import { vsprintf } from 'sprintf-js'
10 |
11 | import formatText from './format_text'
12 | import stringifyAsQueryParam from './stringify_as_query_param'
13 |
14 | const fetch = fetchPonyfill({ Promise })
15 |
16 | export function ResponseError(message, status, requestURI) {
17 | this.name = 'ResponseError'
18 | this.message = message
19 | this.status = status
20 | this.requestURI = requestURI
21 | this.stack = new Error().stack
22 | }
23 |
24 | ResponseError.prototype = new Error()
25 |
26 | /**
27 | * @private
28 | * Timeout function following https://github.com/github/fetch/issues/175#issuecomment-284787564
29 | * @param {integer} obj Source object
30 | * @param {Promise} filter Array of key names to select or function to invoke per iteration
31 | * @param {AbortController} controller AbortController instance bound to fetch
32 | * @return {Object} TimeoutError if the time was consumed, otherwise the Promise will be resolved
33 | */
34 | function timeout(ms, promise, controller) {
35 | return new Promise((resolve, reject) => {
36 | const nodeTimeout = setTimeout(() => {
37 | controller.abort()
38 | const errorObject = {
39 | message: 'TimeoutError',
40 | }
41 | reject(new Error(errorObject))
42 | }, ms)
43 | promise
44 | .then((res) => {
45 | clearTimeout(nodeTimeout)
46 | resolve(res)
47 | })
48 | .catch((err) => {
49 | clearTimeout(nodeTimeout)
50 | reject(err)
51 | })
52 | })
53 | }
54 |
55 | /**
56 | * @private
57 | * @param {Promise} res Source object
58 | * @return {Promise} Promise that will resolve with the response if its status was 2xx;
59 | * otherwise rejects with the response
60 | */
61 | function handleResponse(res) {
62 | // If status is not a 2xx (based on Response.ok), assume it's an error
63 | // See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
64 | if (!(res && res.ok)) {
65 | throw new ResponseError(
66 | 'HTTP Error: Requested page not reachable',
67 | `${res.status} ${res.statusText}`,
68 | res.url
69 | )
70 | }
71 | return res
72 | }
73 |
74 | /**
75 | * @private
76 | * imported from https://github.com/bigchaindb/js-utility-belt/
77 | *
78 | * Global fetch wrapper that adds some basic error handling and ease of use enhancements.
79 | * Considers any non-2xx response as an error.
80 | *
81 | * For more information on fetch, see https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch.
82 | *
83 | * Expects fetch to already be available (either in a ES6 environment, bundled through webpack, or
84 | * injected through a polyfill).
85 | *
86 | * @param {string} url Url to request. Can be specified as a sprintf format string (see
87 | * https://github.com/alexei/sprintf.js) that will be resolved using
88 | * `config.urlTemplateSpec`.
89 | * @param {Object} config Additional configuration, mostly passed to fetch as its 'init' config
90 | * (see https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch#Parameters).
91 | * @param {*} config.jsonBody Json payload to the request. Will automatically be
92 | * JSON.stringify()-ed and override `config.body`.
93 | * @param {string|Object} config.query Query parameter to append to the end of the url.
94 | * If specified as an object, keys will be
95 | * decamelized into snake case first.
96 | * @param {*[]|Object} config.urlTemplateSpec Format spec to use to expand the url (see sprintf).
97 | * @param {*} config.* All other options are passed through to fetch.
98 | * @param {integer} requestTimeout Timeout for a single request
99 | *
100 | * @return {Promise} If requestTimeout the timeout function will be called. Otherwise resolve the
101 | * Promise with the handleResponse function
102 | */
103 | export default function baseRequest(
104 | url,
105 | {
106 | jsonBody, query, urlTemplateSpec, ...fetchConfig
107 | } = {},
108 | requestTimeout = 0
109 | ) {
110 | let expandedUrl = url
111 |
112 | if (urlTemplateSpec != null) {
113 | if (Array.isArray(urlTemplateSpec) && urlTemplateSpec.length) {
114 | // Use vsprintf for the array call signature
115 | expandedUrl = vsprintf(url, urlTemplateSpec)
116 | } else if (
117 | urlTemplateSpec &&
118 | typeof urlTemplateSpec === 'object' &&
119 | Object.keys(urlTemplateSpec).length
120 | ) {
121 | expandedUrl = formatText(url, urlTemplateSpec)
122 | } else if (process.env.NODE_ENV !== 'production') {
123 | // eslint-disable-next-line no-console
124 | console.warn(
125 | 'Supplied urlTemplateSpec was not an array or object. Ignoring...'
126 | )
127 | }
128 | }
129 |
130 | if (query != null) {
131 | if (typeof query === 'string') {
132 | expandedUrl += query
133 | } else if (query && typeof query === 'object') {
134 | expandedUrl += stringifyAsQueryParam(query)
135 | } else if (process.env.NODE_ENV !== 'production') {
136 | // eslint-disable-next-line no-console
137 | console.warn('Supplied query was not a string or object. Ignoring...')
138 | }
139 | }
140 |
141 | if (jsonBody != null) {
142 | fetchConfig.body = JSON.stringify(jsonBody)
143 | }
144 |
145 | if (requestTimeout) {
146 | const controller = new AbortController()
147 | const { signal } = controller
148 | return timeout(
149 | requestTimeout,
150 | fetch.fetch(expandedUrl, { ...fetchConfig, signal }),
151 | controller
152 | )
153 | .then(handleResponse)
154 | } else {
155 | return fetch.fetch(expandedUrl, fetchConfig).then(handleResponse)
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/connection.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import Transport from './transport'
6 |
7 | const HEADER_BLACKLIST = ['content-type']
8 | const DEFAULT_NODE = 'http://localhost:9984/api/v1/'
9 | const DEFAULT_TIMEOUT = 20000 // The default value is 20 seconds
10 |
11 | /**
12 | *
13 | * @param {String, Array} nodes Nodes for the connection. String possible to be backwards compatible
14 | * with version before 4.1.0 version
15 | * @param {Object} headers Common headers for every request
16 | * @param {float} timeout Optional timeout in secs
17 | *
18 | *
19 | */
20 |
21 | export default class Connection {
22 | // This driver implements the BEP-14 https://github.com/bigchaindb/BEPs/tree/master/14
23 | constructor(nodes, headers = {}, timeout = DEFAULT_TIMEOUT) {
24 | // Copy object
25 | this.headers = { ...headers }
26 |
27 | // Validate headers
28 | Object.keys(headers).forEach(header => {
29 | if (HEADER_BLACKLIST.includes(header.toLowerCase())) {
30 | throw new Error(`Header ${header} is reserved and cannot be set.`)
31 | }
32 | })
33 |
34 | this.normalizedNodes = []
35 | if (!nodes) {
36 | this.normalizedNodes.push(Connection.normalizeNode(DEFAULT_NODE, this.headers))
37 | } else if (Array.isArray(nodes)) {
38 | nodes.forEach(node => {
39 | this.normalizedNodes.push(Connection.normalizeNode(node, this.headers))
40 | })
41 | } else {
42 | this.normalizedNodes.push(Connection.normalizeNode(nodes, this.headers))
43 | }
44 |
45 | this.transport = new Transport(this.normalizedNodes, timeout)
46 | }
47 |
48 | static normalizeNode(node, headers) {
49 | if (typeof node === 'string') {
50 | return { 'endpoint': node, 'headers': headers }
51 | } else {
52 | const allHeaders = { ...headers, ...node.headers }
53 | return { 'endpoint': node.endpoint, 'headers': allHeaders }
54 | }
55 | }
56 |
57 | static getApiUrls(endpoint) {
58 | return {
59 | 'blocks': 'blocks',
60 | 'blocksDetail': 'blocks/%(blockHeight)s',
61 | 'outputs': 'outputs',
62 | 'transactions': 'transactions',
63 | 'transactionsSync': 'transactions?mode=sync',
64 | 'transactionsAsync': 'transactions?mode=async',
65 | 'transactionsCommit': 'transactions?mode=commit',
66 | 'transactionsDetail': 'transactions/%(transactionId)s',
67 | 'assets': 'assets',
68 | 'metadata': 'metadata'
69 | }[endpoint]
70 | }
71 |
72 | _req(path, options = {}) {
73 | return this.transport.forwardRequest(path, options)
74 | }
75 |
76 | /**
77 | * @param blockHeight
78 | */
79 | getBlock(blockHeight) {
80 | return this._req(Connection.getApiUrls('blocksDetail'), {
81 | urlTemplateSpec: {
82 | blockHeight
83 | }
84 | })
85 | }
86 |
87 | /**
88 | * @param transactionId
89 | */
90 | getTransaction(transactionId) {
91 | return this._req(Connection.getApiUrls('transactionsDetail'), {
92 | urlTemplateSpec: {
93 | transactionId
94 | }
95 | })
96 | }
97 |
98 | /**
99 | * @param transactionId
100 | * @param status
101 | */
102 | listBlocks(transactionId) {
103 | return this._req(Connection.getApiUrls('blocks'), {
104 | query: {
105 | transaction_id: transactionId,
106 | }
107 | })
108 | }
109 |
110 | /**
111 | * @param publicKey
112 | * @param spent
113 | */
114 | listOutputs(publicKey, spent) {
115 | const query = {
116 | public_key: publicKey
117 | }
118 | // NOTE: If `spent` is not defined, it must not be included in the
119 | // query parameters.
120 | if (spent !== undefined) {
121 | query.spent = spent.toString()
122 | }
123 | return this._req(Connection.getApiUrls('outputs'), {
124 | query
125 | })
126 | }
127 |
128 | /**
129 | * @param assetId
130 | * @param operation
131 | */
132 | listTransactions(assetId, operation) {
133 | return this._req(Connection.getApiUrls('transactions'), {
134 | query: {
135 | asset_id: assetId,
136 | operation
137 | }
138 | })
139 | }
140 |
141 | /**
142 | * @param transaction
143 | */
144 | postTransaction(transaction) {
145 | return this.postTransactionCommit(transaction)
146 | }
147 |
148 | /**
149 | * @param transaction
150 | */
151 | postTransactionSync(transaction) {
152 | return this._req(Connection.getApiUrls('transactionsSync'), {
153 | method: 'POST',
154 | jsonBody: transaction
155 | })
156 | }
157 |
158 | /**
159 | * @param transaction
160 | */
161 | postTransactionAsync(transaction) {
162 | return this._req(Connection.getApiUrls('transactionsAsync'), {
163 | method: 'POST',
164 | jsonBody: transaction
165 | })
166 | }
167 |
168 | /**
169 | * @param transaction
170 | */
171 | postTransactionCommit(transaction) {
172 | return this._req(Connection.getApiUrls('transactionsCommit'), {
173 | method: 'POST',
174 | jsonBody: transaction
175 | })
176 | }
177 |
178 | /**
179 | * @param search
180 | */
181 | searchAssets(search, limit = 10) {
182 | return this._req(Connection.getApiUrls('assets'), {
183 | query: {
184 | search,
185 | limit
186 | }
187 | })
188 | }
189 |
190 | /**
191 | * @param search
192 | */
193 | searchMetadata(search, limit = 10) {
194 | return this._req(Connection.getApiUrls('metadata'), {
195 | query: {
196 | search,
197 | limit
198 | }
199 | })
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/src/format_text.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import { sprintf } from 'sprintf-js'
6 |
7 | // Regexes taken from or inspired by sprintf-js
8 | const Regex = {
9 | TEMPLATE_LITERAL: /\${([^)]+?)}/g,
10 | KEY: /^([a-z_][a-z_\d]*)/i,
11 | KEY_ACCESS: /^\.([a-z_][a-z_\d]*)/i,
12 | INDEX_ACCESS: /^\[(\d+)\]/
13 | }
14 |
15 | /**
16 | * imported from https://github.com/bigchaindb/js-utility-belt/
17 | * @private
18 | * Formats strings similarly to C's sprintf, with the addition of '${...}' formats.
19 | *
20 | * Makes a first pass replacing '${...}' formats before passing the expanded string and other
21 | * arguments to sprintf-js. For more information on what sprintf can do, see
22 | * https://github.com/alexei/sprintf.js.
23 | *
24 | * Examples:
25 | * formatText('Hi there ${dimi}!', { dimi: 'Dimi' })
26 | * => 'Hi there Dimi!'
27 | *
28 | * formatText('${database} is %(status)s', { database: 'BigchainDB', status: 'big' })
29 | * => 'BigchainDB is big'
30 | *
31 | * Like sprintf-js, string interpolation for keywords and indexes is supported too:
32 | * formatText('Berlin is best known for its ${berlin.topKnownFor[0].name}', {
33 | * berlin: {
34 | * topKnownFor: [{
35 | * name: 'Currywurst'
36 | * }, ...
37 | * ]
38 | * }
39 | * })
40 | * => 'Berlin is best known for its Currywurst'
41 | */
42 | export default function formatText(s, ...argv) {
43 | let expandedFormatStr = s
44 |
45 | // Try to replace formats of the form '${...}' if named replacement fields are used
46 | if (s && argv.length === 1 && typeof argv[0] === 'object') {
47 | const templateSpecObj = argv[0]
48 |
49 | expandedFormatStr = s.replace(Regex.TEMPLATE_LITERAL, (match, replacement) => {
50 | let interpolationLeft = replacement
51 |
52 | /**
53 | * @private
54 | * Interpolation algorithm inspired by sprintf-js.
55 | *
56 | * Goes through the replacement string getting the left-most key or index to interpolate
57 | * on each pass. `value` at each step holds the last interpolation result, `curMatch` is
58 | * the current property match, and `interpolationLeft` is the portion of the replacement
59 | * string still to be interpolated.
60 | *
61 | * It's useful to note that RegExp.exec() returns with an array holding:
62 | * [0]: Full string matched
63 | * [1+]: Matching groups
64 | *
65 | * And that in the regexes defined, the first matching group always corresponds to the
66 | * property matched.
67 | */
68 | let value
69 | let curMatch = Regex.KEY.exec(interpolationLeft)
70 | if (curMatch !== null) {
71 | value = templateSpecObj[curMatch[1]]
72 |
73 | // Assigning in the conditionals here makes the code less bloated
74 | /* eslint-disable no-cond-assign */
75 | while ((interpolationLeft = interpolationLeft.substring(curMatch[0].length)) &&
76 | value != null) {
77 | if ((curMatch = Regex.KEY_ACCESS.exec(interpolationLeft))) {
78 | value = value[curMatch[1]]
79 | } else if ((curMatch = Regex.INDEX_ACCESS.exec(interpolationLeft))) {
80 | value = value[curMatch[1]]
81 | } else {
82 | break
83 | }
84 | }
85 | /* eslint-enable no-cond-assign */
86 | }
87 |
88 | // If there's anything left to interpolate by the end then we've failed to interpolate
89 | // the entire replacement string.
90 | if (interpolationLeft.length) {
91 | throw new SyntaxError(`[formatText] failed to parse named argument key: ${replacement}`)
92 | }
93 |
94 | return value
95 | })
96 | }
97 |
98 | return sprintf(expandedFormatStr, ...argv)
99 | }
100 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import Ed25519Keypair from './Ed25519Keypair'
6 | import Connection from './connection'
7 | import Transaction from './transaction'
8 | import ccJsonLoad from './utils/ccJsonLoad'
9 | import ccJsonify from './utils/ccJsonify'
10 |
11 | export {
12 | ccJsonLoad, ccJsonify, Connection, Ed25519Keypair, Transaction
13 | }
14 |
--------------------------------------------------------------------------------
/src/request.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import baseRequest from './baseRequest'
6 | import sanitize from './sanitize'
7 |
8 | const DEFAULT_REQUEST_CONFIG = {
9 | headers: {
10 | 'Accept': 'application/json'
11 | }
12 | }
13 |
14 | const BACKOFF_DELAY = 500 // 0.5 seconds
15 | const ERROR_FROM_SERVER = 'HTTP Error: Requested page not reachable'
16 | /**
17 | * @private
18 | * Small wrapper around js-utility-belt's request that provides url resolving,
19 | * default settings, and response handling.
20 | */
21 |
22 | export default class Request {
23 | constructor(node) {
24 | this.node = node
25 | this.backoffTime = null
26 | this.retries = 0
27 | this.connectionError = null
28 | }
29 |
30 | async request(urlPath, config, timeout, maxBackoffTime) {
31 | if (!urlPath) {
32 | return Promise.reject(new Error('Request was not given a url.'))
33 | }
34 | // Load default fetch configuration and remove any falsy query parameters
35 | const requestConfig = {
36 | ...this.node.headers,
37 | ...DEFAULT_REQUEST_CONFIG,
38 | ...config,
39 | query: config.query && sanitize(config.query)
40 | }
41 | const apiUrl = this.node.endpoint + urlPath
42 | if (requestConfig.jsonBody) {
43 | requestConfig.headers = { ...requestConfig.headers, 'Content-Type': 'application/json' }
44 | }
45 |
46 | // If connectionError occurs, a timestamp equal to now +
47 | // `backoffTimedelta` is assigned to the object.
48 | // Next time the function is called, it either
49 | // waits till the timestamp is passed or raises `TimeoutError`.
50 | // If `ConnectionError` occurs two or more times in a row,
51 | // the retry count is incremented and the new timestamp is calculated
52 | // as now + the `backoffTimedelta`
53 | // The `backoffTimedelta` is the minimum between the default delay
54 | // multiplied by two to the power of the
55 | // number of retries or timeout/2 or 10. See Transport class for that
56 | // If a request is successful, the backoff timestamp is removed,
57 | // the retry count is back to zero.
58 |
59 | const backoffTimedelta = this.getBackoffTimedelta()
60 |
61 | if (timeout != null && timeout < backoffTimedelta) {
62 | const errorObject = {
63 | message: 'TimeoutError'
64 | }
65 | throw errorObject
66 | }
67 | if (backoffTimedelta > 0) {
68 | await Request.sleep(backoffTimedelta)
69 | }
70 |
71 | const requestTimeout = timeout ? timeout - backoffTimedelta : timeout
72 | return baseRequest(apiUrl, requestConfig, requestTimeout)
73 | .then((res) => {
74 | this.connectionError = null
75 | return res.json()
76 | })
77 | .catch(err => {
78 | // ConnectionError
79 | this.connectionError = err
80 | })
81 | .finally(() => {
82 | this.updateBackoffTime(maxBackoffTime)
83 | })
84 | }
85 |
86 | updateBackoffTime(maxBackoffTime) {
87 | if (!this.connectionError) {
88 | this.retries = 0
89 | this.backoffTime = null
90 | } else if (this.connectionError.message === ERROR_FROM_SERVER) {
91 | // If status is not a 2xx (based on Response.ok), throw error
92 | this.retries = 0
93 | this.backoffTime = null
94 | throw this.connectionError
95 | } else {
96 | // Timeout or no connection could be stablished
97 | const backoffTimedelta = Math.min(BACKOFF_DELAY * (2 ** this.retries), maxBackoffTime)
98 | this.backoffTime = Date.now() + backoffTimedelta
99 | this.retries += 1
100 | if (this.connectionError.message === 'TimeoutError') {
101 | throw this.connectionError
102 | }
103 | }
104 | }
105 |
106 | getBackoffTimedelta() {
107 | if (!this.backoffTime) {
108 | return 0
109 | }
110 | return (this.backoffTime - Date.now())
111 | }
112 |
113 | static sleep(ms) {
114 | return new Promise(resolve => {
115 | setTimeout(resolve, ms)
116 | })
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/src/sanitize.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import 'core-js/features/array/includes'
6 | import 'core-js/features/object/entries'
7 |
8 | /**
9 | * @private
10 | * Abstraction for selectFromObject and omitFromObject for DRYness.
11 | * Set isInclusion to true if the filter should be for including the filtered items (ie. selecting
12 | * only them vs omitting only them).
13 | */
14 | function filterFromObject(obj, filter, { isInclusion = true } = {}) {
15 | if (filter && Array.isArray(filter)) {
16 | return applyFilterOnObject(obj, isInclusion ? (val => filter.includes(val))
17 | : (val => !filter.includes(val)))
18 | } else if (filter && typeof filter === 'function') {
19 | // Flip the filter fn's return if it's for inclusion
20 | return applyFilterOnObject(obj, isInclusion ? filter
21 | : (...args) => !filter(...args))
22 | } else {
23 | throw new Error('The given filter is not an array or function. Filter aborted')
24 | }
25 | }
26 |
27 | /**
28 | * @private
29 | * Returns a filtered copy of the given object's own enumerable properties (no inherited
30 | * properties), keeping any keys that pass the given filter function.
31 | */
32 | function applyFilterOnObject(obj, filterFn) {
33 | if (filterFn == null) {
34 | return { ...obj }
35 | }
36 |
37 | const filteredObj = {}
38 | Object.entries(obj).forEach(([key, val]) => {
39 | if (filterFn(val, key)) {
40 | filteredObj[key] = val
41 | }
42 | })
43 |
44 | return filteredObj
45 | }
46 |
47 | /**
48 | * @private
49 | * Similar to lodash's _.pick(), this returns a copy of the given object's
50 | * own and inherited enumerable properties, selecting only the keys in
51 | * the given array or whose value pass the given filter function.
52 | * @param {Object} obj Source object
53 | * @param {Array|function} filter Array of key names to select or function to invoke per iteration
54 | * @return {Object} The new object
55 | */
56 | function selectFromObject(obj, filter) {
57 | return filterFromObject(obj, filter)
58 | }
59 |
60 | /**
61 | * @private
62 | * Glorified selectFromObject. Takes an object and returns a filtered shallow copy that strips out
63 | * any properties that are falsy (including coercions, ie. undefined, null, '', 0, ...).
64 | * Does not modify the passed in object.
65 | *
66 | * @param {Object} obj Javascript object
67 | * @return {Object} Sanitized Javascript object
68 | */
69 | export default function sanitize(obj) {
70 | return selectFromObject(obj, (val) => !!val)
71 | }
72 |
--------------------------------------------------------------------------------
/src/sha256Hash.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable camelcase */
6 | import { sha3_256 } from 'js-sha3'
7 |
8 | export default function sha256Hash(data) {
9 | return sha3_256
10 | .create()
11 | .update(data)
12 | .hex()
13 | }
14 | /* eslint-enable camelcase */
15 |
--------------------------------------------------------------------------------
/src/stringify_as_query_param.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import 'core-js/features/object/entries'
6 | import decamelize from 'decamelize'
7 | import queryString from 'query-string'
8 |
9 | /**
10 | * @private
11 | * imported from https://github.com/bigchaindb/js-utility-belt/
12 | *
13 | * Takes a key-value dictionary (ie. object) and converts it to a query-parameter string that you
14 | * can directly append into a URL.
15 | *
16 | * Extends queryString.stringify by allowing you to specify a `transform` function that will be
17 | * invoked on each of the dictionary's keys before being stringified into the query-parameter
18 | * string.
19 | *
20 | * By default `transform` is `decamelize`, so a dictionary of the form:
21 | *
22 | * {
23 | * page: 1,
24 | * pageSize: 10
25 | * }
26 | *
27 | * will be converted to a string like:
28 | *
29 | * ?page=1&page_size=10
30 | *
31 | * @param {Object} obj Query params dictionary
32 | * @param {function} [transform=decamelize] Transform function for each of the param keys
33 | * @return {string} Query param string
34 | */
35 | export default function stringifyAsQueryParam(obj, transform = decamelize) {
36 | if (!obj || typeof obj !== 'object' || !Object.keys(obj).length) {
37 | return ''
38 | }
39 |
40 | const transformedKeysObj = Object.entries(obj).reduce((paramsObj, [key, value]) => {
41 | paramsObj[transform(key)] = value
42 | return paramsObj
43 | }, {})
44 |
45 | return `?${queryString.stringify(transformedKeysObj)}`
46 | }
47 |
--------------------------------------------------------------------------------
/src/transaction.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import stableStringify from 'json-stable-stringify'
6 | import clone from 'clone'
7 | import base58 from 'bs58'
8 | import { Ed25519Sha256, PreimageSha256, ThresholdSha256 } from 'crypto-conditions'
9 | import ccJsonify from './utils/ccJsonify'
10 | import sha256Hash from './sha256Hash'
11 |
12 | /**
13 | * Construct Transactions
14 | */
15 | export default class Transaction {
16 | /**
17 | * Canonically serializes a transaction into a string by sorting the keys
18 | * @param {Object} (transaction)
19 | * @return {string} a canonically serialized Transaction
20 | */
21 | static serializeTransactionIntoCanonicalString(transaction) {
22 | // BigchainDB signs fulfillments by serializing transactions into a
23 | // "canonical" format where
24 | const tx = clone(transaction)
25 | // TODO: set fulfillments to null
26 | // Sort the keys
27 | return stableStringify(tx, (a, b) => (a.key > b.key ? 1 : -1))
28 | }
29 |
30 | static makeInputTemplate(publicKeys = [], fulfills = null, fulfillment = null) {
31 | return {
32 | fulfillment,
33 | fulfills,
34 | 'owners_before': publicKeys,
35 | }
36 | }
37 |
38 | static makeTransactionTemplate() {
39 | const txTemplate = {
40 | id: null,
41 | operation: null,
42 | outputs: [],
43 | inputs: [],
44 | metadata: null,
45 | asset: null,
46 | version: '2.0',
47 | }
48 | return txTemplate
49 | }
50 |
51 | static makeTransaction(operation, asset, metadata = null, outputs = [], inputs = []) {
52 | const tx = Transaction.makeTransactionTemplate()
53 | tx.operation = operation
54 | tx.asset = asset
55 | tx.metadata = metadata
56 | tx.inputs = inputs
57 | tx.outputs = outputs
58 | return tx
59 | }
60 |
61 | /**
62 | * Generate a `CREATE` transaction holding the `asset`, `metadata`, and `outputs`, to be signed by
63 | * the `issuers`.
64 | * @param {Object} asset Created asset's data
65 | * @param {Object} metadata Metadata for the Transaction
66 | * @param {Object[]} outputs Array of Output objects to add to the Transaction.
67 | * Think of these as the recipients of the asset after the transaction.
68 | * For `CREATE` Transactions, this should usually just be a list of
69 | * Outputs wrapping Ed25519 Conditions generated from the issuers' public
70 | * keys (so that the issuers are the recipients of the created asset).
71 | * @param {...string[]} issuers Public key of one or more issuers to the asset being created by this
72 | * Transaction.
73 | * Note: Each of the private keys corresponding to the given public
74 | * keys MUST be used later (and in the same order) when signing the
75 | * Transaction (`signTransaction()`).
76 | * @returns {Object} Unsigned transaction -- make sure to call signTransaction() on it before
77 | * sending it off!
78 | */
79 | static makeCreateTransaction(asset, metadata, outputs, ...issuers) {
80 | const assetDefinition = {
81 | data: asset || null,
82 | }
83 | const inputs = issuers.map((issuer) => Transaction.makeInputTemplate([issuer]))
84 |
85 | return Transaction.makeTransaction('CREATE', assetDefinition, metadata, outputs, inputs)
86 | }
87 |
88 | /**
89 | * Create an Ed25519 Cryptocondition from an Ed25519 public key
90 | * to put into an Output of a Transaction
91 | * @param {string} publicKey base58 encoded Ed25519 public key for the recipient of the Transaction
92 | * @param {boolean} [json=true] If true returns a json object otherwise a crypto-condition type
93 | * @returns {Object} Ed25519 Condition (that will need to wrapped in an Output)
94 | */
95 | static makeEd25519Condition(publicKey, json = true) {
96 | const publicKeyBuffer = base58.decode(publicKey)
97 | const ed25519Fulfillment = new Ed25519Sha256()
98 | ed25519Fulfillment.setPublicKey(publicKeyBuffer)
99 | return json ? ccJsonify(ed25519Fulfillment) : ed25519Fulfillment
100 | }
101 |
102 | /**
103 | * Create an Output from a Condition.
104 | * Note: Assumes the given Condition was generated from a
105 | * single public key (e.g. a Ed25519 Condition)
106 | * @param {Object} condition Condition (e.g. a Ed25519 Condition from `makeEd25519Condition()`)
107 | * @param {string} amount Amount of the output
108 | * @returns {Object} An Output usable in a Transaction
109 | */
110 | static makeOutput(condition, amount = '1') {
111 | if (typeof amount !== 'string') {
112 | throw new TypeError('`amount` must be of type string')
113 | }
114 | const publicKeys = []
115 | const getPublicKeys = details => {
116 | if (details.type === 'ed25519-sha-256') {
117 | if (!publicKeys.includes(details.public_key)) {
118 | publicKeys.push(details.public_key)
119 | }
120 | } else if (details.type === 'threshold-sha-256') {
121 | details.subconditions.map(getPublicKeys)
122 | }
123 | }
124 | getPublicKeys(condition.details)
125 | return {
126 | condition,
127 | amount,
128 | public_keys: publicKeys,
129 | }
130 | }
131 |
132 | /**
133 | * Create a Preimage-Sha256 Cryptocondition from a secret to put into an Output of a Transaction
134 | * @param {string} preimage Preimage to be hashed and wrapped in a crypto-condition
135 | * @param {boolean} [json=true] If true returns a json object otherwise a crypto-condition type
136 | * @returns {Object} Preimage-Sha256 Condition (that will need to wrapped in an Output)
137 | */
138 | static makeSha256Condition(preimage, json = true) {
139 | const sha256Fulfillment = new PreimageSha256()
140 | sha256Fulfillment.setPreimage(Buffer.from(preimage))
141 | return json ? ccJsonify(sha256Fulfillment) : sha256Fulfillment
142 | }
143 |
144 | /**
145 | * Create an Sha256 Threshold Cryptocondition from threshold to put into an Output of a Transaction
146 | * @param {number} threshold
147 | * @param {Array} [subconditions=[]]
148 | * @param {boolean} [json=true] If true returns a json object otherwise a crypto-condition type
149 | * @returns {Object} Sha256 Threshold Condition (that will need to wrapped in an Output)
150 | */
151 | static makeThresholdCondition(threshold, subconditions = [], json = true) {
152 | const thresholdCondition = new ThresholdSha256()
153 | thresholdCondition.setThreshold(threshold)
154 | subconditions.forEach((subcondition) => {
155 | // TODO: add support for Condition
156 | thresholdCondition.addSubfulfillment(subcondition)
157 | // ? Should be thresholdCondition.addSubcondition(subcondition)
158 | })
159 |
160 | return json ? ccJsonify(thresholdCondition) : thresholdCondition
161 | }
162 |
163 | /**
164 | * Generate a `TRANSFER` transaction holding the `asset`, `metadata`, and `outputs`, that fulfills
165 | * the `fulfilledOutputs` of `unspentTransaction`.
166 | * @param {Object} unspentTransaction Previous Transaction you have control over (i.e. can fulfill
167 | * its Output Condition)
168 | * @param {Object} metadata Metadata for the Transaction
169 | * @param {Object[]} outputs Array of Output objects to add to the Transaction.
170 | * Think of these as the recipients of the asset after the transaction.
171 | * For `TRANSFER` Transactions, this should usually just be a list of
172 | * Outputs wrapping Ed25519 Conditions generated from the public keys of
173 | * the recipients.
174 | * @param {...number} OutputIndices Indices of the Outputs in `unspentTransaction` that this
175 | * Transaction fulfills.
176 | * Note that listed public keys listed must be used (and in
177 | * the same order) to sign the Transaction
178 | * (`signTransaction()`).
179 | * @returns {Object} Unsigned transaction -- make sure to call signTransaction() on it before
180 | * sending it off!
181 | */
182 | // TODO:
183 | // - Make `metadata` optional argument
184 | static makeTransferTransaction(
185 | unspentOutputs,
186 | outputs,
187 | metadata
188 | ) {
189 | const inputs = unspentOutputs.map((unspentOutput) => {
190 | const { tx, outputIndex } = { tx: unspentOutput.tx, outputIndex: unspentOutput.output_index }
191 | const fulfilledOutput = tx.outputs[outputIndex]
192 | const transactionLink = {
193 | output_index: outputIndex,
194 | transaction_id: tx.id,
195 | }
196 |
197 | return Transaction.makeInputTemplate(fulfilledOutput.public_keys, transactionLink)
198 | })
199 |
200 | const assetLink = {
201 | id: unspentOutputs[0].tx.operation === 'CREATE' ? unspentOutputs[0].tx.id
202 | : unspentOutputs[0].tx.asset.id
203 | }
204 | return Transaction.makeTransaction('TRANSFER', assetLink, metadata, outputs, inputs)
205 | }
206 |
207 | /**
208 | * Sign the given `transaction` with the given `privateKey`s, returning a new copy of `transaction`
209 | * that's been signed.
210 | * Note: Only generates Ed25519 Fulfillments. Thresholds and other types of Fulfillments are left as
211 | * an exercise for the user.
212 | * @param {Object} transaction Transaction to sign. `transaction` is not modified.
213 | * @param {...string} privateKeys Private keys associated with the issuers of the `transaction`.
214 | * Looped through to iteratively sign any Input Fulfillments found in
215 | * the `transaction`.
216 | * @returns {Object} The signed version of `transaction`.
217 | */
218 | static signTransaction(transaction, ...privateKeys) {
219 | const signedTx = clone(transaction)
220 | const serializedTransaction =
221 | Transaction.serializeTransactionIntoCanonicalString(transaction)
222 |
223 | signedTx.inputs.forEach((input, index) => {
224 | const privateKey = privateKeys[index]
225 | const privateKeyBuffer = base58.decode(privateKey)
226 |
227 | const transactionUniqueFulfillment = input.fulfills ? serializedTransaction
228 | .concat(input.fulfills.transaction_id)
229 | .concat(input.fulfills.output_index) : serializedTransaction
230 | const transactionHash = sha256Hash(transactionUniqueFulfillment)
231 | const ed25519Fulfillment = new Ed25519Sha256()
232 | ed25519Fulfillment.sign(Buffer.from(transactionHash, 'hex'), privateKeyBuffer)
233 | const fulfillmentUri = ed25519Fulfillment.serializeUri()
234 |
235 | input.fulfillment = fulfillmentUri
236 | })
237 |
238 | const serializedSignedTransaction =
239 | Transaction.serializeTransactionIntoCanonicalString(signedTx)
240 | signedTx.id = sha256Hash(serializedSignedTransaction)
241 | return signedTx
242 | }
243 |
244 | /**
245 | * Delegate signing of the given `transaction` returning a new copy of `transaction`
246 | * that's been signed.
247 | * @param {Object} transaction Transaction to sign. `transaction` is not modified.
248 | * @param {Function} signFn Function signing the transaction, expected to return the fulfillment.
249 | * @returns {Object} The signed version of `transaction`.
250 | */
251 | static delegateSignTransaction(transaction, signFn) {
252 | const signedTx = clone(transaction)
253 | const serializedTransaction =
254 | Transaction.serializeTransactionIntoCanonicalString(transaction)
255 |
256 | signedTx.inputs.forEach((input, index) => {
257 | const fulfillmentUri = signFn(serializedTransaction, input, index)
258 | input.fulfillment = fulfillmentUri
259 | })
260 |
261 | const serializedSignedTransaction = Transaction.serializeTransactionIntoCanonicalString(signedTx)
262 | signedTx.id = sha256Hash(serializedSignedTransaction)
263 | return signedTx
264 | }
265 |
266 | /**
267 | * Delegate signing of the given `transaction` returning a new copy of `transaction`
268 | * that's been signed.
269 | * @param {Object} transaction Transaction to sign. `transaction` is not modified.
270 | * @param {Function} signFn Function signing the transaction, expected to resolve the fulfillment.
271 | * @returns {Promise} The signed version of `transaction`.
272 | */
273 | static async delegateSignTransactionAsync(transaction, signFn) {
274 | const signedTx = clone(transaction)
275 | const serializedTransaction =
276 | Transaction.serializeTransactionIntoCanonicalString(transaction)
277 |
278 | await Promise.all(signedTx.inputs.map(async (input, index) => {
279 | const fulfillmentUri = await signFn(serializedTransaction, input, index)
280 | input.fulfillment = fulfillmentUri
281 | }))
282 |
283 | const serializedSignedTransaction = Transaction.serializeTransactionIntoCanonicalString(signedTx)
284 | signedTx.id = sha256Hash(serializedSignedTransaction)
285 | return signedTx
286 | }
287 | }
288 |
--------------------------------------------------------------------------------
/src/transport.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import Request from './request'
6 |
7 | /**
8 | *
9 | * @private
10 | * If initialized with ``>1`` nodes, the driver will send successive
11 | * requests to different nodes in a round-robin fashion (this will be
12 | * customizable in the future).
13 | */
14 |
15 | export default class Transport {
16 | constructor(nodes, timeout) {
17 | this.connectionPool = []
18 | this.timeout = timeout
19 | // the maximum backoff time is 10 seconds
20 | this.maxBackoffTime = timeout ? timeout / 2 : 10000
21 | nodes.forEach(node => {
22 | this.connectionPool.push(new Request(node))
23 | })
24 | }
25 |
26 | // Select the connection with the earliest backoff time, in case of a tie,
27 | // prefer the one with the smaller list index
28 | pickConnection() {
29 | let connection = this.connectionPool[0]
30 |
31 | this.connectionPool.forEach(conn => {
32 | // 0 the lowest value is the time for Thu Jan 01 1970 01:00:00 GMT+0100 (CET)
33 | conn.backoffTime = conn.backoffTime ? conn.backoffTime : 0
34 | connection = (conn.backoffTime < connection.backoffTime) ? conn : connection
35 | })
36 | return connection
37 | }
38 |
39 | async forwardRequest(path, headers) {
40 | let response
41 | let connection
42 | // A new request will be executed until there is a valid response or timeout < 0
43 | while (this.timeout >= 0) {
44 | connection = this.pickConnection()
45 | // Date in milliseconds
46 | const startTime = Date.now()
47 | // eslint-disable-next-line no-await-in-loop
48 | response = await connection.request(
49 | path,
50 | headers,
51 | this.timeout,
52 | this.maxBackoffTime
53 | )
54 | const elapsed = Date.now() - startTime
55 | if (connection.backoffTime > 0 && this.timeout > 0) {
56 | this.timeout -= elapsed
57 | } else {
58 | // No connection error, the response is valid
59 | return response
60 | }
61 | }
62 | throw new Error('TimeoutError')
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/utils/ccJsonLoad.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import base58 from 'bs58'
6 | import { Condition, Ed25519Sha256, ThresholdSha256 } from 'crypto-conditions'
7 |
8 | /**
9 | * Loads a crypto-condition class (Fulfillment or Condition) from a BigchainDB JSON object
10 | * @param {Object} conditionJson
11 | * @returns {cc.Condition} Ed25519 Condition (that will need to wrapped in an Output)
12 | */
13 | export default function ccJsonLoad(conditionJson) {
14 | if ('hash' in conditionJson) {
15 | const condition = new Condition()
16 | condition.setTypeId(conditionJson.type_id)
17 | condition.setSubtypes(conditionJson.bitmask)
18 | condition.setHash(base58.decode(conditionJson.hash))
19 | // TODO: fix this, maxFulfillmentLength cannot be set in CryptoCondition lib
20 | condition.maxFulfillmentLength = parseInt(conditionJson.max_fulfillment_length, 10)
21 | return condition
22 | } else {
23 | let fulfillment
24 |
25 | if (conditionJson.type === 'threshold-sha-256') {
26 | fulfillment = new ThresholdSha256()
27 | fulfillment.threshold = conditionJson.threshold
28 | conditionJson.subconditions.forEach((subconditionJson) => {
29 | const subcondition = ccJsonLoad(subconditionJson)
30 | if ('getConditionUri' in subcondition) {
31 | fulfillment.addSubfulfillment(subcondition)
32 | } else if ('serializeUri' in subcondition) {
33 | fulfillment.addSubcondition(subcondition)
34 | }
35 | })
36 | }
37 |
38 | if (conditionJson.type === 'ed25519-sha-256') {
39 | fulfillment = new Ed25519Sha256()
40 | fulfillment.setPublicKey(base58.decode(conditionJson.public_key))
41 | }
42 | return fulfillment
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/utils/ccJsonify.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import base58 from 'bs58'
6 |
7 | /**
8 | * Serializes a crypto-condition class (Condition or Fulfillment) into a BigchainDB-compatible JSON
9 | * @param {cc.Fulfillment} fulfillment base58 encoded Ed25519 public key for recipient of the Transaction
10 | * @returns {Object} Ed25519 Condition (that will need to wrapped in an Output)
11 | */
12 | export default function ccJsonify(fulfillment) {
13 | let conditionUri
14 |
15 | if ('getConditionUri' in fulfillment) {
16 | conditionUri = fulfillment.getConditionUri()
17 | } else if ('serializeUri' in fulfillment) {
18 | conditionUri = fulfillment.serializeUri()
19 | }
20 |
21 | const jsonBody = {
22 | details: {},
23 | uri: conditionUri,
24 | }
25 |
26 | if (fulfillment.getTypeId() === 0) {
27 | jsonBody.details.type_id = 0
28 | jsonBody.details.bitmask = 3
29 |
30 | if ('preimage' in fulfillment) {
31 | jsonBody.details.preimage = fulfillment.preimage.toString()
32 | jsonBody.details.type = 'fulfillment'
33 | }
34 | }
35 |
36 | if (fulfillment.getTypeId() === 2) {
37 | return {
38 | details: {
39 | type: 'threshold-sha-256',
40 | threshold: fulfillment.threshold,
41 | subconditions: fulfillment.subconditions.map((subcondition) => {
42 | const subconditionJson = ccJsonify(subcondition.body)
43 | return subconditionJson.details
44 | })
45 | },
46 | uri: conditionUri,
47 | }
48 | }
49 |
50 | if (fulfillment.getTypeId() === 4) {
51 | jsonBody.details.type = 'ed25519-sha-256'
52 |
53 | if ('publicKey' in fulfillment) {
54 | jsonBody.details.public_key = base58.encode(fulfillment.publicKey)
55 | }
56 | }
57 |
58 | if ('hash' in fulfillment) {
59 | jsonBody.details.hash = base58.encode(fulfillment.hash)
60 | jsonBody.details.max_fulfillment_length = fulfillment.maxFulfillmentLength
61 | jsonBody.details.type = 'condition'
62 | }
63 |
64 | return jsonBody
65 | }
66 |
--------------------------------------------------------------------------------
/test/base-request/test_baseRequest.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import test from 'ava'
6 | import rewire from 'rewire'
7 |
8 | const baseRequestFile = rewire('../../src/baseRequest.js')
9 | const baseRequest = baseRequestFile.__get__('baseRequest')
10 | const handleResponse = baseRequestFile.__get__('handleResponse')
11 |
12 | test('HandleResponse does not throw error for response ok', t => {
13 | const testObj = {
14 | ok: true
15 | }
16 | const expected = testObj
17 | const actual = handleResponse(testObj)
18 |
19 | t.deepEqual(actual, expected)
20 | })
21 |
22 | test('baseRequest test query and vsprint', async t => {
23 | const error = await t.throwsAsync(baseRequest('https://%s.com/', {
24 | urlTemplateSpec: ['google'],
25 | query: 'teapot'
26 | }), { instanceOf: Error, message: 'HTTP Error: Requested page not reachable' })
27 |
28 | t.is(error.requestURI, 'https://www.google.com/teapot')
29 | t.is(error.status, '418 I\'m a Teapot')
30 | })
31 |
--------------------------------------------------------------------------------
/test/connection/test_connection.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import test from 'ava'
6 | import sinon from 'sinon'
7 |
8 | import {
9 | Connection
10 | } from '../../src'
11 | import {
12 | API_PATH
13 | } from '../constants'
14 |
15 | const conn = new Connection(API_PATH)
16 |
17 | test('Payload thrown at incorrect API_PATH', async t => {
18 | const path = 'http://localhost:9984/api/wrong/'
19 | const connection = new Connection(path)
20 | const target = {
21 | message: 'HTTP Error: Requested page not reachable',
22 | status: '404 NOT FOUND',
23 | requestURI: 'http://localhost:9984/api/wrong/transactions/transactionId'
24 | }
25 | const error = await t.throwsAsync(connection.getTransaction('transactionId'), {
26 | instanceOf: Error, message: target.message
27 | })
28 |
29 | t.is('ResponseError', error.name)
30 | t.is(target.status, error.status)
31 | t.is(target.requestURI, error.requestURI)
32 | })
33 |
34 | test('Generate API URLS', t => {
35 | const endpoints = {
36 | 'blocks': 'blocks',
37 | 'blocksDetail': 'blocks/%(blockHeight)s',
38 | 'outputs': 'outputs',
39 | 'transactions': 'transactions',
40 | 'transactionsSync': 'transactions?mode=sync',
41 | 'transactionsAsync': 'transactions?mode=async',
42 | 'transactionsCommit': 'transactions?mode=commit',
43 | 'transactionsDetail': 'transactions/%(transactionId)s',
44 | 'assets': 'assets',
45 | }
46 | Object.keys(endpoints).forEach(endpointName => {
47 | const url = Connection.getApiUrls(endpointName)
48 | const expected = endpoints[endpointName]
49 | t.is(url, expected)
50 | })
51 | })
52 |
53 | test('Normalize node from an object', t => {
54 | const headers = {
55 | custom: 'headers'
56 | }
57 | const node = {
58 | endpoint: API_PATH,
59 | headers: {
60 | hello: 'world'
61 | }
62 | }
63 | const expectedNode = {
64 | 'endpoint': API_PATH,
65 | 'headers': {
66 | hello: 'world',
67 | custom: 'headers'
68 | }
69 | }
70 |
71 | t.deepEqual(Connection.normalizeNode(node, headers), expectedNode)
72 | })
73 |
74 | test('Normalize node from a string', t => {
75 | const headers = {
76 | custom: 'headers'
77 | }
78 | const expectedNode = {
79 | 'endpoint': API_PATH,
80 | 'headers': {
81 | custom: 'headers'
82 | }
83 | }
84 |
85 | t.deepEqual(Connection.normalizeNode(API_PATH, headers), expectedNode)
86 | })
87 |
88 | test('Request with custom headers', t => {
89 | const testConn = new Connection(API_PATH, {
90 | hello: 'world'
91 | })
92 | const expectedOptions = {
93 | headers: {
94 | custom: 'headers'
95 | }
96 | }
97 | const PATH = 'blocks'
98 | testConn.transport.forwardRequest = sinon.spy()
99 |
100 | testConn._req(PATH, {
101 | headers: {
102 | custom: 'headers'
103 | }
104 | })
105 | t.truthy(testConn.transport.forwardRequest.calledWith(PATH, expectedOptions))
106 | })
107 |
108 | test('Get block for a block id', t => {
109 | const expectedPath = 'path'
110 | const blockHeight = 'abc'
111 |
112 | conn._req = sinon.spy()
113 | Connection.getApiUrls = sinon.stub().returns(expectedPath)
114 |
115 | conn.getBlock(blockHeight)
116 | t.truthy(conn._req.calledWith(
117 | expectedPath,
118 | { urlTemplateSpec: { blockHeight } }
119 | ))
120 | })
121 |
122 | test('Get transaction for a transaction id', t => {
123 | const expectedPath = 'path'
124 | const transactionId = 'abc'
125 |
126 | conn._req = sinon.spy()
127 | Connection.getApiUrls = sinon.stub().returns(expectedPath)
128 |
129 | conn.getTransaction(transactionId)
130 | t.truthy(conn._req.calledWith(
131 | expectedPath,
132 | { urlTemplateSpec: { transactionId } }
133 | ))
134 | })
135 |
136 | test('Get list of blocks for a transaction id', t => {
137 | const expectedPath = 'path'
138 | const transactionId = 'abc'
139 |
140 | conn._req = sinon.spy()
141 | Connection.getApiUrls = sinon.stub().returns(expectedPath)
142 |
143 | conn.listBlocks(transactionId)
144 | t.truthy(conn._req.calledWith(
145 | expectedPath,
146 | {
147 | query: {
148 | transaction_id: transactionId,
149 | }
150 | }
151 | ))
152 | })
153 |
154 | test('Get list of transactions for an asset id', t => {
155 | const expectedPath = 'path'
156 | const assetId = 'abc'
157 | const operation = 'operation'
158 |
159 | conn._req = sinon.spy()
160 | Connection.getApiUrls = sinon.stub().returns(expectedPath)
161 |
162 | conn.listTransactions(assetId, operation)
163 | t.truthy(conn._req.calledWith(
164 | expectedPath,
165 | {
166 | query: {
167 | asset_id: assetId,
168 | operation
169 | }
170 | }
171 | ))
172 | })
173 |
174 | test('Get outputs for a public key and no spent flag', t => {
175 | const expectedPath = 'path'
176 | const publicKey = 'publicKey'
177 |
178 | conn._req = sinon.spy()
179 | Connection.getApiUrls = sinon.stub().returns(expectedPath)
180 |
181 | conn.listOutputs(publicKey)
182 | t.truthy(conn._req.calledWith(
183 | expectedPath,
184 | { query: { public_key: publicKey } }
185 | ))
186 | })
187 |
188 | test('Get outputs for a public key and spent=false', t => {
189 | const expectedPath = 'path'
190 | const publicKey = 'publicKey'
191 | const spent = false
192 |
193 | conn._req = sinon.spy()
194 | Connection.getApiUrls = sinon.stub().returns(expectedPath)
195 |
196 | conn.listOutputs(publicKey, spent)
197 | t.truthy(conn._req.calledWith(
198 | expectedPath,
199 | { query: { public_key: publicKey, spent: 'false' } }
200 | ))
201 | })
202 |
203 | test('Get outputs for a public key and spent=true', t => {
204 | const expectedPath = 'path'
205 | const publicKey = 'publicKey'
206 | const spent = true
207 |
208 | conn._req = sinon.spy()
209 | Connection.getApiUrls = sinon.stub().returns(expectedPath)
210 |
211 | conn.listOutputs(publicKey, spent)
212 | t.truthy(conn._req.calledWith(
213 | expectedPath,
214 | { query: { public_key: publicKey, spent: 'true' } }
215 | ))
216 | })
217 |
218 | test('Get asset for text', t => {
219 | const expectedPath = 'path'
220 | const search = 'abc'
221 |
222 | conn._req = sinon.spy()
223 | Connection.getApiUrls = sinon.stub().returns(expectedPath)
224 |
225 | conn.searchAssets(search)
226 | t.truthy(conn._req.calledWith(
227 | expectedPath,
228 | { query: { search, limit: 10 } }
229 | ))
230 | })
231 |
232 | test('Get metadata for text', t => {
233 | const expectedPath = 'path'
234 | const search = 'abc'
235 |
236 | conn._req = sinon.spy()
237 | Connection.getApiUrls = sinon.stub().returns(expectedPath)
238 |
239 | conn.searchMetadata(search)
240 | t.truthy(conn._req.calledWith(
241 | expectedPath,
242 | { query: { search, limit: 10 } }
243 | ))
244 | })
245 |
--------------------------------------------------------------------------------
/test/constants.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import { createHash } from 'crypto'
6 | import base58 from 'bs58'
7 | import { Ed25519Sha256 } from 'crypto-conditions'
8 | import { Transaction, Ed25519Keypair } from '../src'
9 | // TODO: Find out if ava has something like conftest, if so put this there.
10 |
11 | // NOTE: It's safer to cast `Math.random()` to a string, to avoid differences
12 | // in "float interpretation" between languages (e.g. JavaScript and Python)
13 | export const API_PATH = 'http://localhost:9984/api/v1/'
14 | export function asset() { return { message: `${Math.random()}` } }
15 | export const metaData = { message: 'metaDataMessage' }
16 |
17 | export const alice = new Ed25519Keypair()
18 | export const aliceCondition = Transaction.makeEd25519Condition(alice.publicKey)
19 | export const aliceOutput = Transaction.makeOutput(aliceCondition)
20 | export const createTx = Transaction.makeCreateTransaction(
21 | asset,
22 | metaData,
23 | [aliceOutput],
24 | alice.publicKey
25 | )
26 | export const transferTx = Transaction.makeTransferTransaction(
27 | [{ tx: createTx, output_index: 0 }],
28 | [aliceOutput],
29 | metaData
30 | )
31 |
32 | export const bob = new Ed25519Keypair()
33 | export const bobCondition = Transaction.makeEd25519Condition(bob.publicKey)
34 | export const bobOutput = Transaction.makeOutput(bobCondition)
35 |
36 | export function delegatedSignTransaction(...keyPairs) {
37 | return function sign(serializedTransaction, input) {
38 | const transactionUniqueFulfillment = input.fulfills ? serializedTransaction
39 | .concat(input.fulfills.transaction_id)
40 | .concat(input.fulfills.output_index) : serializedTransaction
41 | const transactionHash = createHash('sha3-256').update(transactionUniqueFulfillment).digest()
42 | const filteredKeyPairs = keyPairs.filter(
43 | ({ publicKey }) => input.owners_before.includes(publicKey)
44 | )
45 |
46 | const ed25519Fulfillment = new Ed25519Sha256()
47 | filteredKeyPairs.forEach(keyPair => {
48 | const privateKey = Buffer.from(base58.decode(keyPair.privateKey))
49 | ed25519Fulfillment.sign(transactionHash, privateKey)
50 | })
51 | return ed25519Fulfillment.serializeUri()
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/test/integration/test_integration.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import test from 'ava'
6 | import { Ed25519Keypair, Transaction, Connection } from '../../src'
7 |
8 | import {
9 | API_PATH,
10 | alice,
11 | aliceCondition,
12 | aliceOutput,
13 | bob,
14 | bobOutput,
15 | asset,
16 | metaData,
17 | delegatedSignTransaction
18 | } from '../constants'
19 |
20 | test('Keypair is created', t => {
21 | const keyPair = new Ed25519Keypair()
22 |
23 | t.truthy(keyPair.publicKey)
24 | t.truthy(keyPair.privateKey)
25 | })
26 |
27 | test('Valid CREATE transaction with default node', t => {
28 | const conn = new Connection()
29 |
30 | const tx = Transaction.makeCreateTransaction(
31 | asset(),
32 | metaData,
33 | [aliceOutput],
34 | alice.publicKey
35 | )
36 | const txSigned = Transaction.signTransaction(tx, alice.privateKey)
37 |
38 | return conn.postTransaction(txSigned)
39 | .then(resTx => {
40 | t.truthy(resTx)
41 | })
42 | })
43 |
44 | test('Valid CREATE transaction using async', t => {
45 | const conn = new Connection(API_PATH)
46 |
47 | const tx = Transaction.makeCreateTransaction(
48 | asset(),
49 | metaData,
50 | [aliceOutput],
51 | alice.publicKey
52 | )
53 | const txSigned = Transaction.signTransaction(tx, alice.privateKey)
54 |
55 | return conn.postTransactionAsync(txSigned)
56 | .then(resTx => t.truthy(resTx))
57 | })
58 |
59 | test('Valid CREATE transaction using sync', t => {
60 | const conn = new Connection(API_PATH)
61 |
62 | const tx = Transaction.makeCreateTransaction(
63 | asset(),
64 | metaData,
65 | [aliceOutput],
66 | alice.publicKey
67 | )
68 | const txSigned = Transaction.signTransaction(tx, alice.privateKey)
69 |
70 | return conn.postTransactionSync(txSigned)
71 | .then(resTx => t.truthy(resTx))
72 | })
73 |
74 | test('Valid TRANSFER transaction with single Ed25519 input', t => {
75 | const conn = new Connection(API_PATH)
76 | const createTx = Transaction.makeCreateTransaction(
77 | asset(),
78 | metaData,
79 | [aliceOutput],
80 | alice.publicKey
81 | )
82 | const createTxSigned = Transaction.signTransaction(
83 | createTx,
84 | alice.privateKey
85 | )
86 |
87 | return conn.postTransactionCommit(createTxSigned)
88 | .then(() => {
89 | const transferTx = Transaction.makeTransferTransaction(
90 | [{ tx: createTxSigned, output_index: 0 }],
91 | [aliceOutput],
92 | metaData
93 | )
94 | const transferTxSigned = Transaction.signTransaction(
95 | transferTx,
96 | alice.privateKey
97 | )
98 | return conn.postTransactionCommit(transferTxSigned)
99 | .then(resTx => t.truthy(resTx))
100 | })
101 | })
102 |
103 | test('Valid TRANSFER transaction with multiple Ed25519 inputs', t => {
104 | const conn = new Connection(API_PATH)
105 | const createTx = Transaction.makeCreateTransaction(
106 | asset(),
107 | metaData,
108 | [aliceOutput, bobOutput],
109 | alice.publicKey
110 | )
111 | const createTxSigned = Transaction.signTransaction(
112 | createTx,
113 | alice.privateKey
114 | )
115 |
116 | return conn.postTransactionCommit(createTxSigned)
117 | .then(() => {
118 | const transferTx = Transaction.makeTransferTransaction(
119 | [{ tx: createTxSigned, output_index: 0 }, { tx: createTxSigned, output_index: 1 }],
120 | [Transaction.makeOutput(aliceCondition, '2')],
121 | metaData
122 | )
123 | const transferTxSigned = Transaction.signTransaction(
124 | transferTx,
125 | alice.privateKey,
126 | bob.privateKey
127 | )
128 | return conn.postTransactionCommit(transferTxSigned)
129 | .then(resTx => t.truthy(resTx))
130 | })
131 | })
132 |
133 | test('Valid TRANSFER transaction with multiple Ed25519 inputs from different transactions', t => {
134 | const conn = new Connection(API_PATH)
135 | const carol = new Ed25519Keypair()
136 | const carolCondition = Transaction.makeEd25519Condition(carol.publicKey)
137 | const carolOutput = Transaction.makeOutput(carolCondition)
138 | const trent = new Ed25519Keypair()
139 | const trentCondition = Transaction.makeEd25519Condition(trent.publicKey)
140 | const trentOutput = Transaction.makeOutput(trentCondition)
141 | const eli = new Ed25519Keypair()
142 | const eliCondition = Transaction.makeEd25519Condition(eli.publicKey)
143 |
144 | const createTx = Transaction.makeCreateTransaction(
145 | asset(),
146 | metaData,
147 | [aliceOutput, bobOutput],
148 | alice.publicKey
149 | )
150 | const createTxSigned = Transaction.signTransaction(
151 | createTx,
152 | alice.privateKey
153 | )
154 |
155 | return conn.postTransactionCommit(createTxSigned)
156 | .then(() => {
157 | const transferTx1 = Transaction.makeTransferTransaction(
158 | [{ tx: createTxSigned, output_index: 0 }],
159 | [carolOutput],
160 | metaData
161 | )
162 | const transferTxSigned1 = Transaction.signTransaction(
163 | transferTx1,
164 | alice.privateKey
165 | )
166 | const transferTx2 = Transaction.makeTransferTransaction(
167 | [{ tx: createTxSigned, output_index: 1 }],
168 | [trentOutput],
169 | metaData
170 | )
171 | const transferTxSigned2 = Transaction.signTransaction(
172 | transferTx2,
173 | bob.privateKey
174 | )
175 |
176 | return conn.postTransactionCommit(transferTxSigned1)
177 | .then(() => conn.postTransactionCommit(transferTxSigned2))
178 | .then(() => {
179 | const transferTxMultipleInputs = Transaction.makeTransferTransaction(
180 | [{ tx: transferTxSigned1, output_index: 0 },
181 | { tx: transferTxSigned2, output_index: 0 }],
182 | [Transaction.makeOutput(eliCondition, '2')],
183 | metaData
184 | )
185 | const transferTxSignedMultipleInputs = Transaction.signTransaction(
186 | transferTxMultipleInputs,
187 | carol.privateKey,
188 | trent.privateKey
189 | )
190 | return conn.postTransactionCommit(transferTxSignedMultipleInputs)
191 | .then(resTx => t.truthy(resTx))
192 | })
193 | })
194 | })
195 |
196 | test('Valid CREATE transaction using delegateSign with default node', t => {
197 | const conn = new Connection()
198 |
199 | const tx = Transaction.makeCreateTransaction(
200 | asset(),
201 | metaData,
202 | [aliceOutput],
203 | alice.publicKey
204 | )
205 |
206 | const txSigned = Transaction.delegateSignTransaction(
207 | tx,
208 | delegatedSignTransaction(alice)
209 | )
210 |
211 | return conn.postTransaction(txSigned)
212 | .then(resTx => {
213 | t.truthy(resTx)
214 | })
215 | })
216 |
217 | test('Valid TRANSFER transaction with multiple Ed25519 inputs using delegateSign', t => {
218 | const conn = new Connection(API_PATH)
219 | const createTx = Transaction.makeCreateTransaction(
220 | asset(),
221 | metaData,
222 | [aliceOutput, bobOutput],
223 | alice.publicKey
224 | )
225 | const createTxSigned = Transaction.signTransaction(
226 | createTx,
227 | alice.privateKey
228 | )
229 |
230 | return conn.postTransactionCommit(createTxSigned)
231 | .then(() => {
232 | const transferTx = Transaction.makeTransferTransaction(
233 | [{ tx: createTxSigned, output_index: 0 }, { tx: createTxSigned, output_index: 1 }],
234 | [Transaction.makeOutput(aliceCondition, '2')],
235 | metaData
236 | )
237 |
238 | const transferTxSigned = Transaction.delegateSignTransaction(
239 | transferTx,
240 | delegatedSignTransaction(alice, bob)
241 | )
242 |
243 | return conn.postTransactionCommit(transferTxSigned)
244 | .then(resTx => t.truthy(resTx))
245 | })
246 | })
247 |
248 | test('Search for spent and unspent outputs of a given public key', t => {
249 | const conn = new Connection(API_PATH)
250 | const carol = new Ed25519Keypair()
251 | const carolCondition = Transaction.makeEd25519Condition(carol.publicKey)
252 | const carolOutput = Transaction.makeOutput(carolCondition)
253 | const trent = new Ed25519Keypair()
254 | const trentCondition = Transaction.makeEd25519Condition(trent.publicKey)
255 | const trentOutput = Transaction.makeOutput(trentCondition)
256 |
257 | const createTx = Transaction.makeCreateTransaction(
258 | asset(),
259 | metaData,
260 | [carolOutput, carolOutput],
261 | carol.publicKey
262 | )
263 | const createTxSigned = Transaction.signTransaction(
264 | createTx,
265 | carol.privateKey,
266 | carol.privateKey
267 | )
268 |
269 | // We spent output 1 (of 0, 1)
270 | const transferTx = Transaction.makeTransferTransaction(
271 | [{ tx: createTxSigned, output_index: 1 }],
272 | [trentOutput],
273 | metaData
274 | )
275 | const transferTxSigned = Transaction.signTransaction(
276 | transferTx,
277 | carol.privateKey,
278 | )
279 |
280 | return conn.postTransactionCommit(createTxSigned)
281 | .then(() => conn.postTransactionCommit(transferTxSigned))
282 | .then(() => conn.listOutputs(carol.publicKey))
283 | // now listOutputs should return us outputs 0 and 1 (unfiltered)
284 | .then(outputs => t.truthy(outputs.length === 2))
285 | })
286 |
287 | test('Search for unspent outputs for a given public key', t => {
288 | const conn = new Connection(API_PATH)
289 | const carol = new Ed25519Keypair()
290 | const carolCondition = Transaction.makeEd25519Condition(carol.publicKey)
291 | const carolOutput = Transaction.makeOutput(carolCondition)
292 | const trent = new Ed25519Keypair()
293 | const trentCondition = Transaction.makeEd25519Condition(trent.publicKey)
294 | const trentOutput = Transaction.makeOutput(trentCondition)
295 |
296 | const createTx = Transaction.makeCreateTransaction(
297 | asset(),
298 | metaData,
299 | [carolOutput, carolOutput, carolOutput],
300 | carol.publicKey
301 | )
302 | const createTxSigned = Transaction.signTransaction(
303 | createTx,
304 | carol.privateKey,
305 | carol.privateKey
306 | )
307 |
308 | // We spent output 1 (of 0, 1, 2)
309 | const transferTx = Transaction.makeTransferTransaction(
310 | [{ tx: createTxSigned, output_index: 1 }],
311 | [trentOutput],
312 | metaData
313 | )
314 | const transferTxSigned = Transaction.signTransaction(
315 | transferTx,
316 | carol.privateKey,
317 | )
318 |
319 | return conn.postTransactionCommit(createTxSigned)
320 | .then(() => conn.postTransactionCommit(transferTxSigned))
321 | // now listOutputs should return us outputs 0 and 2 (1 is spent)
322 | .then(() => conn.listOutputs(carol.publicKey, 'false'))
323 | .then(outputs => t.truthy(outputs.length === 2))
324 | })
325 |
326 | test('Search for spent outputs for a given public key', t => {
327 | const conn = new Connection(API_PATH)
328 | const carol = new Ed25519Keypair()
329 | const carolCondition = Transaction.makeEd25519Condition(carol.publicKey)
330 | const carolOutput = Transaction.makeOutput(carolCondition)
331 | const trent = new Ed25519Keypair()
332 | const trentCondition = Transaction.makeEd25519Condition(trent.publicKey)
333 | const trentOutput = Transaction.makeOutput(trentCondition)
334 |
335 | const createTx = Transaction.makeCreateTransaction(
336 | asset(),
337 | metaData,
338 | [carolOutput, carolOutput, carolOutput],
339 | carol.publicKey
340 | )
341 | const createTxSigned = Transaction.signTransaction(
342 | createTx,
343 | carol.privateKey,
344 | carol.privateKey
345 | )
346 |
347 | // We spent output 1 (of 0, 1, 2)
348 | const transferTx = Transaction.makeTransferTransaction(
349 | [{ tx: createTxSigned, output_index: 1 }],
350 | [trentOutput],
351 | metaData
352 | )
353 | const transferTxSigned = Transaction.signTransaction(
354 | transferTx,
355 | carol.privateKey,
356 | )
357 |
358 | return conn.postTransactionCommit(createTxSigned)
359 | .then(() => conn.postTransactionCommit(transferTxSigned))
360 | // now listOutputs should only return us output 1 (0 and 2 are unspent)
361 | .then(() => conn.listOutputs(carol.publicKey, true))
362 | .then(outputs => t.truthy(outputs.length === 1))
363 | })
364 |
365 | test('Search for an asset', t => {
366 | const conn = new Connection(API_PATH)
367 |
368 | const createTx = Transaction.makeCreateTransaction(
369 | asset(),
370 | metaData,
371 | [aliceOutput],
372 | alice.publicKey
373 | )
374 | const createTxSigned = Transaction.signTransaction(
375 | createTx,
376 | alice.privateKey
377 | )
378 |
379 | return conn.postTransactionCommit(createTxSigned)
380 | .then(() => conn.searchAssets(createTxSigned.asset.data.message))
381 | .then(assets => t.truthy(
382 | assets.pop(),
383 | createTxSigned.asset.data.message
384 | ))
385 | })
386 |
387 | test('Search for metadata', t => {
388 | const conn = new Connection(API_PATH)
389 |
390 | const createTx = Transaction.makeCreateTransaction(
391 | asset(),
392 | metaData,
393 | [aliceOutput],
394 | alice.publicKey
395 | )
396 | const createTxSigned = Transaction.signTransaction(
397 | createTx,
398 | alice.privateKey
399 | )
400 |
401 | return conn.postTransactionCommit(createTxSigned)
402 | .then(() => conn.searchMetadata(createTxSigned.metadata.message))
403 | .then(assets => t.truthy(
404 | assets.pop(),
405 | createTxSigned.metadata.message
406 | ))
407 | })
408 |
409 | test('Search blocks containing a transaction', t => {
410 | const conn = new Connection(API_PATH)
411 |
412 | const createTx = Transaction.makeCreateTransaction(
413 | asset(),
414 | metaData,
415 | [aliceOutput],
416 | alice.publicKey
417 | )
418 | const createTxSigned = Transaction.signTransaction(
419 | createTx,
420 | alice.privateKey
421 | )
422 |
423 | return conn.postTransactionCommit(createTxSigned)
424 | .then(({ id }) => conn.listBlocks(id))
425 | .then(blockHeight => conn.getBlock(blockHeight.pop()))
426 | .then(({ transactions }) => transactions.filter(({ id }) => id === createTxSigned.id))
427 | .then(transactions => t.truthy(transactions.length === 1))
428 | })
429 |
430 | test('Search transaction containing an asset', t => {
431 | const conn = new Connection(API_PATH)
432 |
433 | const createTx = Transaction.makeCreateTransaction(
434 | asset(),
435 | metaData,
436 | [aliceOutput],
437 | alice.publicKey
438 | )
439 | const createTxSigned = Transaction.signTransaction(
440 | createTx,
441 | alice.privateKey
442 | )
443 |
444 | return conn.postTransactionCommit(createTxSigned)
445 | .then(({ id }) => conn.listTransactions(id))
446 | .then(transactions => {
447 | t.truthy(transactions.length === 1)
448 | })
449 | })
450 |
451 | test('Content-Type cannot be set', t => {
452 | t.throws(() => new Connection(API_PATH, { 'Content-Type': 'application/json' }), {
453 | instanceOf: Error
454 | })
455 | })
456 |
--------------------------------------------------------------------------------
/test/request/test_request.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import test from 'ava'
6 | import Connection from '../../src/connection'
7 |
8 | const conn = new Connection()
9 |
10 | test('Ensure that BackoffTimedelta works properly', t => {
11 | const req = conn.transport.pickConnection()
12 | req.backoffTime = Date.now() + 50
13 | const target = req.getBackoffTimedelta()
14 | // The value should be close to 50
15 | t.is(target > 45, true)
16 | })
17 |
18 | test('Ensure that updateBackoffTime throws and error on TimeoutError', async t => {
19 | const req = conn.transport.pickConnection()
20 | const errorMessage = 'TimeoutError'
21 | req.connectionError = new Error(errorMessage)
22 |
23 | t.throws(() => {
24 | req.updateBackoffTime()
25 | }, { instanceOf: Error, message: errorMessage })
26 | })
27 |
--------------------------------------------------------------------------------
/test/sanitize/test_sanitize.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import test from 'ava'
6 | import rewire from 'rewire'
7 |
8 | const sanitize = rewire('../../src/sanitize.js')
9 | const applyFilterOnObject = sanitize.__get__('applyFilterOnObject')
10 | const filterFromObject = sanitize.__get__('filterFromObject')
11 |
12 | test('Ensure that null filter returns same object', t => {
13 | const expected = { 'testObj': 'test' }
14 | const actual = applyFilterOnObject({ 'testObj': 'test' }, null)
15 |
16 | t.deepEqual(actual, expected)
17 | })
18 |
19 | test('Ensure function filter with isInclusion true works properly', t => {
20 | const testObj = [true, false, undefined, '', 0, null]
21 | const expected = { 0: true }
22 | const actual = filterFromObject(testObj, (val) => !!val, { isInclusion: true })
23 |
24 | t.deepEqual(actual, expected)
25 | })
26 |
27 | test('Ensure function filter with isInclusion false works properly', t => {
28 | const testObj = [false, true, 1, 10, 'this will be removed as it is truthy']
29 | const expected = { 0: false }
30 | const actual = filterFromObject(testObj, (val) => !!val, { isInclusion: false })
31 |
32 | t.deepEqual(actual, expected)
33 | })
34 |
35 | test('Ensure array filter with isInclusion true works properly', t => {
36 | const testObj = [true, false, undefined, '', 0, null]
37 | const expected = { 0: true }
38 | const actual = filterFromObject(testObj, [true], { isInclusion: true })
39 |
40 | t.deepEqual(actual, expected)
41 | })
42 |
43 | test('Ensure array filter with isInclusion false works properly', t => {
44 | const testObj = [false, true, 1, 10]
45 | const expected = { 0: false }
46 | const actual = filterFromObject(testObj, [true, 1, 10], { isInclusion: false })
47 |
48 | t.deepEqual(actual, expected)
49 | })
50 |
51 | test('Ensure throws error when given invalid filter', t => {
52 | t.throws(() => {
53 | filterFromObject({}, 'lol')
54 | }, { instanceOf: Error, message: 'The given filter is not an array or function. Filter aborted' })
55 | })
56 |
--------------------------------------------------------------------------------
/test/text-format/test_format_text.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import test from 'ava'
6 | import formatText from '../../src/format_text'
7 |
8 | test('formatText test type 1', t => {
9 | const expected = 'Hi there Dimi!'
10 | const actual = formatText('Hi there ${dimi}!', { dimi: 'Dimi' }) // eslint-disable-line no-template-curly-in-string
11 |
12 | t.is(actual, expected)
13 | })
14 |
15 | test('formatText test type 2', t => {
16 | const expected = 'BigchainDB is big'
17 | const actual = formatText('${database} is %(status)s', { // eslint-disable-line no-template-curly-in-string
18 | database: 'BigchainDB',
19 | status: 'big'
20 | })
21 |
22 | t.is(actual, expected)
23 | })
24 |
25 | test('formatText test type 3', t => {
26 | const expected = 'Berlin is best known for its Currywurst'
27 | const actual = formatText(
28 | 'Berlin is best known for its ${berlin.topKnownFor[0].name}', // eslint-disable-line no-template-curly-in-string
29 | {
30 | berlin: {
31 | topKnownFor: [
32 | {
33 | name: 'Currywurst'
34 | }
35 | ]
36 | }
37 | }
38 | )
39 |
40 | t.is(actual, expected)
41 | })
42 |
43 | test('formatText test throws', t => {
44 | t.throws(() => {
45 | formatText(
46 | 'This will give ${error.}', // eslint-disable-line no-template-curly-in-string
47 | { error: [{}] }
48 | )
49 | }, { instanceOf: SyntaxError, message: '[formatText] failed to parse named argument key: error.' })
50 | })
51 |
--------------------------------------------------------------------------------
/test/transaction/test_cryptoconditions.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import { createHash } from 'crypto'
6 | import { validateFulfillment } from 'crypto-conditions'
7 | import test from 'ava'
8 | import base58 from 'bs58'
9 | import { Ed25519Keypair, Transaction, ccJsonLoad } from '../../src'
10 | import { delegatedSignTransaction } from '../constants'
11 | import sha256Hash from '../../src/sha256Hash'
12 |
13 | test('Ed25519 condition encoding', t => {
14 | const publicKey = '4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS'
15 | const target = {
16 | details: {
17 | type: 'ed25519-sha-256',
18 | public_key: publicKey,
19 | },
20 | uri: 'ni:///sha-256;uLdVX7FEjLWVDkAkfMAkEqPPwFqZj7qfiGE152t_x5c?fpt=ed25519-sha-256&cost=131072'
21 | }
22 | t.deepEqual(target, Transaction.makeEd25519Condition(publicKey))
23 | })
24 |
25 | test('Sha256Condition fulfillment', t => {
26 | const preimage = 'secret'
27 | const target = {
28 | details: {
29 | type_id: 0,
30 | bitmask: 3,
31 | preimage,
32 | type: 'fulfillment'
33 | },
34 | uri: 'ni:///sha-256;K7gNU3sdo-OL0wNhqoVWhr3g6s1xYv72ol_pe_Unols?fpt=preimage-sha-256&cost=6'
35 | }
36 | t.deepEqual(target, Transaction.makeSha256Condition(preimage))
37 | })
38 |
39 | test('Threshold condition encoding', t => {
40 | const publicKey = '4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS'
41 | const ed25519 = Transaction.makeEd25519Condition(publicKey, false)
42 | const condition = Transaction.makeThresholdCondition(1, [ed25519, ed25519])
43 | const output = Transaction.makeOutput(condition)
44 | const target = {
45 | condition: {
46 | details: {
47 | type: 'threshold-sha-256',
48 | threshold: 1,
49 | subconditions: [
50 | {
51 | type: 'ed25519-sha-256',
52 | public_key: publicKey,
53 | },
54 | {
55 | type: 'ed25519-sha-256',
56 | public_key: publicKey,
57 | }
58 | ]
59 | },
60 | uri: 'ni:///sha-256;xTeBhQj7ae5Tym7cp83fwtkesQnhdwNwDEMIYwnf2g0?fpt=threshold-sha-256&cost=133120&subtypes=ed25519-sha-256',
61 | },
62 | amount: '1',
63 | public_keys: [publicKey]
64 | }
65 | t.deepEqual(target, output)
66 | })
67 |
68 | test('Fulfillment correctly formed', t => {
69 | const alice = new Ed25519Keypair()
70 | const txCreate = Transaction.makeCreateTransaction(
71 | {},
72 | {},
73 | [Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
74 | alice.publicKey
75 | )
76 | // Sign in order to get the tx id, needed for the unique fulfillment in the transfer transaction
77 | const signCreateTransaction = Transaction.signTransaction(txCreate, alice.privateKey)
78 |
79 | const txTransfer = Transaction.makeTransferTransaction(
80 | [{ tx: signCreateTransaction, output_index: 0 }],
81 | [Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
82 | {}
83 | )
84 | const txSigned = Transaction.signTransaction(txTransfer, alice.privateKey)
85 |
86 | // Here reconstruct the fulfillment of the transfer transaction
87 | // The tx is serialized, and extended with tx_id and output index, and then hashed into bytes
88 | const msg = Transaction.serializeTransactionIntoCanonicalString(txTransfer)
89 | const msgUniqueFulfillment = txTransfer.inputs[0].fulfills ? msg
90 | .concat(txTransfer.inputs[0].fulfills.transaction_id)
91 | .concat(txTransfer.inputs[0].fulfills.output_index) : msg
92 | const msgHash = sha256Hash(msgUniqueFulfillment)
93 |
94 | t.truthy(validateFulfillment(
95 | txSigned.inputs[0].fulfillment,
96 | txCreate.outputs[0].condition.uri,
97 | Buffer.from(msgHash, 'hex')
98 | ))
99 | })
100 |
101 | test('Delegated signature is correct', t => {
102 | const alice = new Ed25519Keypair()
103 |
104 | const txCreate = Transaction.makeCreateTransaction(
105 | {},
106 | {},
107 | [Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
108 | alice.publicKey
109 | )
110 |
111 | const signCreateTransaction = Transaction.signTransaction(txCreate, alice.privateKey)
112 | const delegatedSignCreateTransaction = Transaction.delegateSignTransaction(
113 | txCreate,
114 | delegatedSignTransaction(alice)
115 | )
116 | t.deepEqual(signCreateTransaction, delegatedSignCreateTransaction)
117 | })
118 |
119 | test('Delegated async signature is correct', async t => {
120 | const alice = new Ed25519Keypair()
121 |
122 | const txCreate = Transaction.makeCreateTransaction(
123 | {},
124 | {},
125 | [Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
126 | alice.publicKey
127 | )
128 |
129 | const signCreateTransaction = Transaction.signTransaction(txCreate, alice.privateKey)
130 | const delegatedSignCreateTransaction = await Transaction.delegateSignTransactionAsync(
131 | txCreate,
132 | delegatedSignTransaction(alice)
133 | )
134 | t.deepEqual(signCreateTransaction, delegatedSignCreateTransaction)
135 | })
136 |
137 | test('CryptoConditions JSON load', t => {
138 | const publicKey = '4zvwRjXUKGfvwnParsHAS3HuSVzV5cA4McphgmoCtajS'
139 | const cond = ccJsonLoad({
140 | type: 'threshold-sha-256',
141 | threshold: 1,
142 | subconditions: [{
143 | type: 'ed25519-sha-256',
144 | public_key: publicKey
145 | },
146 | {
147 | hash: base58.encode(createHash('sha256').update('a').digest())
148 | }],
149 | })
150 | t.truthy(cond.subconditions.length === 2)
151 | })
152 |
--------------------------------------------------------------------------------
/test/transaction/test_transaction.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import test from 'ava'
6 | import sinon from 'sinon'
7 |
8 | import { Transaction } from '../../src'
9 |
10 | import {
11 | alice,
12 | aliceOutput,
13 | metaData,
14 | createTx,
15 | transferTx
16 | } from '../constants'
17 |
18 | test('Create valid output with default amount', t => {
19 | const condition = {
20 | details: {
21 | type: 'ed25519-sha-256',
22 | public_key: 'abc'
23 | }
24 | }
25 | const expected = {
26 | amount: '1',
27 | condition,
28 | public_keys: ['abc']
29 | }
30 | const res = Transaction.makeOutput(condition)
31 | t.deepEqual(res, expected)
32 | })
33 |
34 | test('Create valid output with custom amount', t => {
35 | const condition = {
36 | details: {
37 | type: 'ed25519-sha-256',
38 | public_key: 'abc'
39 | }
40 | }
41 | const customAmount = '1337'
42 | const expected = {
43 | amount: customAmount,
44 | condition,
45 | public_keys: ['abc']
46 | }
47 | const res = Transaction.makeOutput(condition, customAmount)
48 | t.deepEqual(res, expected)
49 | })
50 |
51 | test('Pass condition not based on public_keys to makeOutput', t => {
52 | const condition = {
53 | details: {
54 | idea: 'just pretend this is e.g. a hashlock'
55 | }
56 | }
57 | const expected = {
58 | amount: '1',
59 | condition,
60 | public_keys: []
61 | }
62 | const res = Transaction.makeOutput(condition)
63 | t.deepEqual(res, expected)
64 | })
65 |
66 | test('makeOutput throws TypeError with incorrect amount type', t => {
67 | t.throws(() => Transaction.makeOutput({}, 1337), { instanceOf: TypeError })
68 | })
69 |
70 | test('Create TRANSFER transaction based on CREATE transaction', t => {
71 | sinon.spy(Transaction, 'makeTransaction')
72 | Transaction.makeTransferTransaction(
73 | [{ tx: createTx, output_index: 0 }],
74 | [aliceOutput],
75 | metaData
76 | )
77 | const expected = [
78 | 'TRANSFER',
79 | { id: createTx.id },
80 | metaData,
81 | [aliceOutput],
82 | [Transaction.makeInputTemplate(
83 | [alice.publicKey],
84 | { output_index: 0, transaction_id: createTx.id }
85 | )]
86 | ]
87 | // NOTE: `src/transaction/makeTransaction` is `export default`, hence we
88 | // can only mock `makeTransaction.default` with a hack:
89 | // See: https://stackoverflow.com/a/33676328/1263876
90 | t.truthy(Transaction.makeTransaction.calledWith(...expected))
91 | Transaction.makeTransaction.restore()
92 | })
93 |
94 | test('Create TRANSFER transaction based on TRANSFER transaction', t => {
95 | sinon.spy(Transaction, 'makeTransaction')
96 |
97 | Transaction.makeTransferTransaction(
98 | [{ tx: transferTx, output_index: 0 }],
99 | [aliceOutput],
100 | metaData
101 | )
102 | const expected = [
103 | 'TRANSFER',
104 | { id: transferTx.asset.id },
105 | metaData,
106 | [aliceOutput],
107 | [Transaction.makeInputTemplate(
108 | [alice.publicKey],
109 | { output_index: 0, transaction_id: transferTx.id }
110 | )]
111 | ]
112 |
113 | t.truthy(Transaction.makeTransaction.calledWith(...expected))
114 | Transaction.makeTransaction.restore()
115 | })
116 |
--------------------------------------------------------------------------------
/test/transport/test_transport.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import test from 'ava'
6 |
7 | import {
8 | Connection
9 | } from '../../src'
10 |
11 | test('Pick connection with earliest backoff time', async t => {
12 | const path1 = 'http://localhost:9984/api/v1/'
13 | const path2 = 'http://localhostwrong:9984/api/v1/'
14 |
15 | // Reverse order
16 | const conn = new Connection([path2, path1])
17 | // This will trigger the 'forwardRequest' so the correct connection will be taken
18 | await conn.searchAssets('example')
19 |
20 | const connection1 = conn.transport.connectionPool[1]
21 |
22 | t.deepEqual(conn.transport.pickConnection(), connection1)
23 | })
24 |
--------------------------------------------------------------------------------
/types/Ed25519Keypair.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | export default class Ed25519Keypair {
6 | publicKey: string;
7 | privateKey: string;
8 |
9 | constructor(seed?: Buffer);
10 | }
11 |
--------------------------------------------------------------------------------
/types/baseRequest.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | export interface RequestConfig {
6 | headers?: Record;
7 | jsonBody?: Record;
8 | query?: Record;
9 | method?: 'GET' | ' POST' | 'PUT';
10 | urlTemplateSpec?: any[] | Record;
11 | [key: string]: any;
12 | }
13 |
14 | export function ResponseError(
15 | message: string,
16 | status?: number,
17 | requestURI?: string
18 | ): void;
19 |
20 | declare function timeout(
21 | ms: number,
22 | promise: Promise
23 | ): Promise;
24 |
25 | declare function handleResponse(res: Response): Response;
26 |
27 | export default function baseRequest(
28 | url: string,
29 | config: RequestConfig,
30 | requestTimeout?: number
31 | ): Promise;
32 |
--------------------------------------------------------------------------------
/types/connection.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import type { RequestConfig } from './baseRequest';
6 | import type { Node } from './request';
7 | import type Transport from './transport';
8 | import type {
9 | CreateTransaction,
10 | TransactionOperations,
11 | TransferTransaction,
12 | TransactionCommon,
13 | } from './transaction';
14 |
15 | declare const DEFAULT_NODE = 'http://localhost:9984/api/v1/';
16 | declare const DEFAULT_TIMEOUT = 20000; // The default value is 20 seconds
17 |
18 | export interface InputNode {
19 | endpoint: string;
20 | }
21 |
22 | export type AssetResult = {
23 | id: string;
24 | data: Record;
25 | };
26 |
27 | export type MetadataResult = {
28 | id: string;
29 | metadata: Record;
30 | };
31 |
32 | export enum Endpoints {
33 | blocks = 'blocks',
34 | blocksDetail = 'blocksDetail',
35 | outputs = 'outputs',
36 | transactions = 'transactions',
37 | transactionsSync = 'transactionsSync',
38 | transactionsAsync = 'transactionsAsync',
39 | transactionsCommit = 'transactionsCommit',
40 | transactionsDetail = 'transactionsDetail',
41 | assets = 'assets',
42 | metadata = 'metadata',
43 | }
44 |
45 | export interface EndpointsUrl {
46 | [Endpoints.blocks]: 'blocks';
47 | [Endpoints.blocksDetail]: 'blocks/%(blockHeight)s';
48 | [Endpoints.outputs]: 'outputs';
49 | [Endpoints.transactions]: 'transactions';
50 | [Endpoints.transactionsSync]: 'transactions?mode=sync';
51 | [Endpoints.transactionsAsync]: 'transactions?mode=async';
52 | [Endpoints.transactionsCommit]: 'transactions?mode=commit';
53 | [Endpoints.transactionsDetail]: 'transactions/%(transactionId)s';
54 | [Endpoints.assets]: 'assets';
55 | [Endpoints.metadata]: 'metadata';
56 | }
57 |
58 | export interface EndpointsResponse<
59 | O = TransactionOperations.CREATE,
60 | A = Record,
61 | M = Record
62 | > {
63 | [Endpoints.blocks]: number[];
64 | [Endpoints.blocksDetail]: {
65 | height: number;
66 | transactions: (CreateTransaction | TransferTransaction)[];
67 | };
68 | [Endpoints.outputs]: {
69 | transaction_id: string;
70 | output_index: number;
71 | }[];
72 | [Endpoints.transactions]: O extends TransactionOperations.CREATE
73 | ? CreateTransaction[]
74 | : O extends TransactionOperations.TRANSFER
75 | ? TransferTransaction[]
76 | : (CreateTransaction | TransferTransaction)[];
77 | [Endpoints.transactionsSync]: O extends TransactionOperations.CREATE
78 | ? CreateTransaction
79 | : TransferTransaction;
80 | [Endpoints.transactionsAsync]: O extends TransactionOperations.CREATE
81 | ? CreateTransaction
82 | : TransferTransaction;
83 | [Endpoints.transactionsCommit]: O extends TransactionOperations.CREATE
84 | ? CreateTransaction
85 | : TransferTransaction;
86 | [Endpoints.transactionsDetail]: O extends TransactionOperations.CREATE
87 | ? CreateTransaction
88 | : TransferTransaction;
89 | [Endpoints.assets]: AssetResult[];
90 | [Endpoints.metadata]: MetadataResult[];
91 | }
92 |
93 | export default class Connection {
94 | private transport: Transport;
95 | private normalizedNodes: Node[];
96 | private headers: Record;
97 |
98 | constructor(
99 | nodes: string | InputNode | (string | InputNode)[],
100 | headers?: Record,
101 | timeout?: number
102 | );
103 |
104 | static normalizeNode(
105 | node: string | InputNode,
106 | headers: Record
107 | ): Node;
108 |
109 | static getApiUrls(endpoint: E): EndpointsUrl[E];
110 |
111 | private _req>(
112 | path: EndpointsUrl[E],
113 | options: RequestConfig
114 | ): Promise;
115 |
116 | getBlock(
117 | blockHeight: number | string
118 | ): Promise;
119 |
120 | getTransaction(
121 | transactionId: string
122 | ): Promise[Endpoints.transactionsDetail]>;
123 |
124 | listBlocks(
125 | transactionId: string
126 | ): Promise;
127 |
128 | listOutputs(
129 | publicKey: string,
130 | spent?: boolean
131 | ): Promise;
132 |
133 | listTransactions(
134 | assetId: string,
135 | operation?: TransactionOperations
136 | ): Promise[Endpoints.transactions]>;
137 |
138 | postTransaction<
139 | O extends TransactionOperations = TransactionOperations.CREATE,
140 | A = Record,
141 | M = Record
142 | >(
143 | transaction: TransactionCommon
144 | ): Promise[Endpoints.transactionsCommit]>;
145 |
146 | postTransactionSync<
147 | O extends TransactionOperations = TransactionOperations.CREATE,
148 | A = Record,
149 | M = Record
150 | >(
151 | transaction: TransactionCommon
152 | ): Promise[Endpoints.transactionsSync]>;
153 |
154 | postTransactionAsync<
155 | O extends TransactionOperations = TransactionOperations.CREATE,
156 | A = Record,
157 | M = Record
158 | >(
159 | transaction: TransactionCommon
160 | ): Promise[Endpoints.transactionsAsync]>;
161 |
162 | postTransactionCommit<
163 | O extends TransactionOperations = TransactionOperations.CREATE,
164 | A = Record,
165 | M = Record
166 | >(
167 | transaction: TransactionCommon
168 | ): Promise[Endpoints.transactionsCommit]>;
169 |
170 | searchAssets(
171 | search: string,
172 | limit?: number
173 | ): Promise;
174 |
175 | searchMetadata(
176 | search: string,
177 | limit?: number
178 | ): Promise;
179 | }
180 |
--------------------------------------------------------------------------------
/types/index.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import Ed25519Keypair from './Ed25519Keypair';
6 | import Connection, {
7 | Endpoints,
8 | EndpointsResponse,
9 | EndpointsUrl,
10 | } from './connection';
11 | import Transaction, {
12 | CreateTransaction,
13 | TransactionCommon,
14 | TransactionCommonSigned,
15 | TransactionInput,
16 | TransactionOutput,
17 | TransferTransaction,
18 | TransactionUnspentOutput,
19 | TransactionOperations,
20 | } from './transaction';
21 | import ccJsonLoad from './utils/ccJsonLoad';
22 | import ccJsonify from './utils/ccJsonify';
23 |
24 | export { ccJsonLoad, ccJsonify, Connection, Ed25519Keypair, Transaction };
25 |
26 | // Extras
27 | export {
28 | Endpoints,
29 | EndpointsResponse,
30 | EndpointsUrl,
31 | CreateTransaction,
32 | TransactionCommon,
33 | TransactionCommonSigned,
34 | TransactionInput,
35 | TransactionOutput,
36 | TransferTransaction,
37 | TransactionUnspentOutput,
38 | TransactionOperations,
39 | };
40 |
--------------------------------------------------------------------------------
/types/request.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import type { RequestConfig } from './baseRequest';
6 |
7 | export interface Node {
8 | endpoint: string;
9 | headers: Record;
10 | }
11 |
12 | export default class Request {
13 | private node: Node;
14 | private backoffTime: number;
15 | private retries: number;
16 | private connectionError?: Error;
17 |
18 | constructor(node: Node);
19 |
20 | request>(
21 | urlPath: string,
22 | config?: RequestConfig,
23 | timeout?: number,
24 | maxBackoffTime?: number
25 | ): Promise;
26 |
27 | updateBackoffTime(maxBackoffTime: number): void;
28 |
29 | getBackoffTimedelta(): number;
30 |
31 | static sleep(ms: number): void;
32 | }
33 |
--------------------------------------------------------------------------------
/types/sanitize.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | declare type FilterFn = (val: any, key?: string) => void;
6 |
7 | declare function filterFromObject>(
8 | obj: I,
9 | filter: Array | FilterFn,
10 | conf: { isInclusion?: boolean }
11 | ): Partial;
12 |
13 | declare function applyFilterOnObject>(
14 | obj: I,
15 | filterFn?: FilterFn
16 | ): Partial;
17 |
18 | declare function selectFromObject>(
19 | obj: I,
20 | filter: Array | FilterFn
21 | ): Partial;
22 |
23 | export default function sanitize>(
24 | obj: I
25 | ): Partial | I;
26 |
--------------------------------------------------------------------------------
/types/transaction.d.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | Ed25519Sha256,
3 | Fulfillment,
4 | PreimageSha256,
5 | ThresholdSha256,
6 | } from 'crypto-conditions';
7 | import {
8 | Ed25519Sha256JSONCondition,
9 | PreimageSha256JSONCondition,
10 | ThresholdSha256JSONCondition,
11 | } from './utils/ccJsonify';
12 |
13 | export interface TransactionInput {
14 | fulfillment: string;
15 | fulfills: {
16 | output_index: number;
17 | transaction_id: string;
18 | } | null;
19 | owners_before: string[];
20 | }
21 | export interface TransactionOutput {
22 | amount: string;
23 | condition:
24 | | PreimageSha256JSONCondition
25 | | ThresholdSha256JSONCondition
26 | | Ed25519Sha256JSONCondition;
27 | public_keys: string[];
28 | }
29 |
30 | export enum TransactionOperations {
31 | CREATE = 'CREATE',
32 | TRANSFER = 'TRANSFER',
33 | }
34 |
35 | export interface TransactionCommon<
36 | O extends TransactionOperations = TransactionOperations.CREATE,
37 | A extends Record = Record,
38 | M extends Record = Record
39 | > {
40 | id?: string;
41 | inputs: TransactionInput[];
42 | outputs: TransactionOutput[];
43 | version: string;
44 | metadata: M;
45 | operation: O;
46 | asset: TransactionAssetMap;
47 | }
48 |
49 | export interface TransactionCommonSigned<
50 | O extends TransactionOperations = TransactionOperations.CREATE,
51 | A extends Record = Record,
52 | M extends Record = Record
53 | > extends Omit, 'id'> {
54 | id: string;
55 | }
56 |
57 | export type TransactionAssetMap<
58 | Operation,
59 | A extends Record
60 | > = Operation extends TransactionOperations.CREATE
61 | ? {
62 | data: A;
63 | }
64 | : {
65 | id: string;
66 | };
67 |
68 | export interface CreateTransaction<
69 | A extends Record = Record,
70 | M extends Record = Record
71 | > extends TransactionCommon {
72 | id: string;
73 | asset: TransactionAssetMap;
74 | operation: TransactionOperations.CREATE;
75 | }
76 |
77 | export interface TransferTransaction<
78 | M extends Record = Record
79 | > extends TransactionCommon {
80 | id: string;
81 | asset: TransactionAssetMap;
82 | operation: TransactionOperations.TRANSFER;
83 | }
84 |
85 | export interface TransactionUnspentOutput {
86 | tx: TransactionCommon;
87 | output_index: number;
88 | }
89 |
90 | interface TxTemplate {
91 | id: null;
92 | operation: null;
93 | outputs: [];
94 | inputs: [];
95 | metadata: null;
96 | asset: null;
97 | version: '2.0';
98 | }
99 |
100 | export type DelegateSignFunction = (
101 | serializedTransaction: string,
102 | input: TransactionInput,
103 | index?: number
104 | ) => string;
105 |
106 | export type DelegateSignFunctionAsync = (
107 | serializedTransaction: string,
108 | input: TransactionInput,
109 | index?: number
110 | ) => Promise;
111 |
112 | export default class Transaction {
113 | static serializeTransactionIntoCanonicalString<
114 | O extends TransactionOperations = TransactionOperations
115 | >(transaction: TransactionCommon): string;
116 |
117 | static serializeTransactionIntoCanonicalString(
118 | transaction: CreateTransaction | TransferTransaction
119 | ): string;
120 |
121 | static makeEd25519Condition(publicKey: string): Ed25519Sha256JSONCondition;
122 |
123 | static makeEd25519Condition(
124 | publicKey: string,
125 | json: true
126 | ): Ed25519Sha256JSONCondition;
127 |
128 | static makeEd25519Condition(publicKey: string, json: false): Ed25519Sha256;
129 |
130 | static makeEd25519Condition(
131 | publicKey: string,
132 | json?: boolean
133 | ): Ed25519Sha256 | Ed25519Sha256JSONCondition;
134 |
135 | static makeSha256Condition(preimage: string): PreimageSha256JSONCondition;
136 |
137 | static makeSha256Condition(
138 | preimage: string,
139 | json: true
140 | ): PreimageSha256JSONCondition;
141 |
142 | static makeSha256Condition(preimage: string, json: false): PreimageSha256;
143 |
144 | static makeSha256Condition(
145 | preimage: string,
146 | json?: boolean
147 | ): PreimageSha256 | PreimageSha256JSONCondition;
148 |
149 | static makeThresholdCondition(
150 | threshold: number,
151 | subconditions: (string | Fulfillment)[]
152 | ): ThresholdSha256JSONCondition;
153 |
154 | static makeThresholdCondition(
155 | threshold: number,
156 | subconditions: (string | Fulfillment)[],
157 | json: true
158 | ): ThresholdSha256JSONCondition;
159 |
160 | static makeThresholdCondition(
161 | threshold: number,
162 | subconditions: (string | Fulfillment)[],
163 | json: false
164 | ): ThresholdSha256;
165 |
166 | static makeThresholdCondition(
167 | threshold: number,
168 | subconditions: (string | Fulfillment)[],
169 | json?: boolean
170 | ): ThresholdSha256 | ThresholdSha256JSONCondition;
171 |
172 | static makeInputTemplate(
173 | publicKeys: string[],
174 | fulfills?: TransactionInput['fulfills'],
175 | fulfillment?: TransactionInput['fulfillment']
176 | ): TransactionInput;
177 |
178 | static makeOutput(
179 | condition:
180 | | PreimageSha256JSONCondition
181 | | ThresholdSha256JSONCondition
182 | | Ed25519Sha256JSONCondition,
183 | amount?: string
184 | ): TransactionOutput;
185 |
186 | static makeTransactionTemplate(): TxTemplate;
187 |
188 | static makeTransaction<
189 | O extends TransactionOperations,
190 | A = Record,
191 | M = Record
192 | >(
193 | operation: O,
194 | asset: A,
195 | metadata: M,
196 | outputs: TransactionOutput[],
197 | inputs: TransactionInput[]
198 | ): TransactionCommon;
199 |
200 | static makeCreateTransaction<
201 | A = Record,
202 | M = Record
203 | >(
204 | asset: A,
205 | metadata: M,
206 | outputs: TransactionOutput[],
207 | ...issuers: string[]
208 | ): CreateTransaction;
209 |
210 | static makeTransferTransaction>(
211 | unspentOutputs: TransactionUnspentOutput[],
212 | outputs: TransactionOutput[],
213 | metadata: M
214 | ): TransferTransaction;
215 |
216 | static signTransaction<
217 | O extends TransactionOperations = TransactionOperations.CREATE
218 | >(
219 | transaction: TransactionCommon,
220 | ...privateKeys: string[]
221 | ): TransactionCommonSigned;
222 |
223 | static delegateSignTransaction<
224 | O extends TransactionOperations = TransactionOperations.CREATE
225 | >(
226 | transaction: TransactionCommon,
227 | signFn: DelegateSignFunction
228 | ): TransactionCommonSigned;
229 |
230 | static delegateSignTransactionAsync<
231 | O extends TransactionOperations = TransactionOperations.CREATE
232 | >(
233 | transaction: TransactionCommon,
234 | signFn: DelegateSignFunctionAsync
235 | ): Promise>;
236 | }
237 |
--------------------------------------------------------------------------------
/types/transport.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import Request, { Node } from './request';
6 | import type { RequestConfig } from './baseRequest';
7 |
8 | export default class Transport {
9 | private connectionPool: Request[];
10 | private timeout: number;
11 | private maxBackoffTime: number;
12 |
13 | constructor(nodes: Node[], timeout: number);
14 |
15 | pickConnection(): Request;
16 |
17 | forwardRequest>(
18 | path: string,
19 | config: RequestConfig
20 | ): Promise;
21 | }
22 |
--------------------------------------------------------------------------------
/types/utils/ccJsonLoad.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import type {
6 | Condition,
7 | Ed25519Sha256,
8 | PreimageSha256,
9 | ThresholdSha256,
10 | } from 'crypto-conditions';
11 | import type {
12 | Ed25519Sha256JSONCondition,
13 | JSONCondition,
14 | PreimageSha256JSONCondition,
15 | ThresholdSha256JSONCondition,
16 | } from './ccJsonify';
17 |
18 | declare function ccJsonLoad(
19 | conditionJson: PreimageSha256JSONCondition
20 | ): PreimageSha256;
21 |
22 | declare function ccJsonLoad(
23 | conditionJson: ThresholdSha256JSONCondition
24 | ): ThresholdSha256;
25 |
26 | declare function ccJsonLoad(
27 | conditionJson: Ed25519Sha256JSONCondition
28 | ): Ed25519Sha256;
29 |
30 | declare function ccJsonLoad(conditionJson: JSONCondition): Condition;
31 |
32 | export default ccJsonLoad;
33 |
--------------------------------------------------------------------------------
/types/utils/ccJsonify.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | import type {
6 | Condition,
7 | Ed25519Sha256,
8 | PreimageSha256,
9 | ThresholdSha256,
10 | } from 'crypto-conditions';
11 | import type { TypeId, TypeName } from 'crypto-conditions/types/types';
12 |
13 | interface BaseJSONCondition {
14 | details: {
15 | [key: string]: any;
16 | };
17 | uri: string;
18 | }
19 |
20 | export interface JSONCondition extends BaseJSONCondition {
21 | details: {
22 | type_id: TypeId;
23 | bitmask: number;
24 | type: 'condition';
25 | hash: string;
26 | max_fulfillment_length: number;
27 | };
28 | }
29 |
30 | export interface PreimageSha256JSONCondition extends BaseJSONCondition {
31 | details: {
32 | type_id: TypeId.PreimageSha256;
33 | bitmask: 3;
34 | preimage?: string;
35 | type?: 'fulfillement';
36 | };
37 | }
38 |
39 | export interface ThresholdSha256JSONCondition extends BaseJSONCondition {
40 | details: {
41 | type: TypeName.ThresholdSha256;
42 | subConditions: (Ed25519Sha256JSONCondition | PreimageSha256JSONCondition)[];
43 | };
44 | }
45 |
46 | export interface Ed25519Sha256JSONCondition extends BaseJSONCondition {
47 | details: { type: TypeName.Ed25519Sha256; publicKey?: string };
48 | }
49 |
50 | export type JSONConditionUnion =
51 | | JSONCondition
52 | | PreimageSha256JSONCondition
53 | | ThresholdSha256JSONCondition
54 | | Ed25519Sha256JSONCondition;
55 |
56 | declare function ccJsonify(
57 | fulfillment: PreimageSha256
58 | ): PreimageSha256JSONCondition;
59 |
60 | declare function ccJsonify(
61 | fulfillment: ThresholdSha256
62 | ): ThresholdSha256JSONCondition;
63 |
64 | declare function ccJsonify(
65 | fulfillment: Ed25519Sha256
66 | ): Ed25519Sha256JSONCondition;
67 |
68 | declare function ccJsonify(fulfillment: Condition): JSONCondition;
69 |
70 | export default ccJsonify;
71 |
--------------------------------------------------------------------------------
/webpack.common.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable strict, no-console, object-shorthand */
6 |
7 | 'use strict'
8 |
9 | const { ProvidePlugin } = require('webpack')
10 | const { paths } = require('./webpack.parts')
11 |
12 | module.exports = {
13 | entry: paths.entry,
14 | mode: 'none',
15 | module: {
16 | rules: [
17 | {
18 | test: /\.js$/,
19 | exclude: /node_modules/,
20 | use: {
21 | loader: 'babel-loader',
22 | },
23 | }
24 | ]
25 | },
26 | optimization: {
27 | minimize: true,
28 | emitOnErrors: false
29 | },
30 | resolve: {
31 | extensions: ['.js'],
32 | modules: ['node_modules'],
33 | fallback: {
34 | buffer: require.resolve('buffer/'),
35 | }
36 | },
37 | plugins: [
38 | new ProvidePlugin({
39 | Buffer: ['buffer', 'Buffer']
40 | })
41 | ]
42 | }
43 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable strict, no-console, object-shorthand */
6 |
7 | 'use strict'
8 |
9 | const PRODUCTION = process.env.NODE_ENV === 'production'
10 |
11 | const common = require('./webpack.common')
12 |
13 | const { outputs } = require('./webpack.parts')
14 |
15 | // '[libraryTarget]': [file extension]
16 | const OUTPUT_MAPPING = {
17 | 'amd': 'amd',
18 | 'commonjs': 'cjs',
19 | 'commonjs2': 'cjs2',
20 | 'umd': 'umd',
21 | 'window': 'window',
22 | }
23 |
24 | const OVERRIDES = {
25 | // optimization: {
26 | // minimize: false
27 | // }
28 | }
29 |
30 | if (PRODUCTION) {
31 | module.exports = outputs(common, 'production', OUTPUT_MAPPING, OVERRIDES)
32 | } else {
33 | module.exports = outputs(common, 'development', OUTPUT_MAPPING, OVERRIDES)
34 | }
35 |
--------------------------------------------------------------------------------
/webpack.development.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable strict, no-console, object-shorthand, import/no-extraneous-dependencies */
6 |
7 | 'use strict'
8 |
9 | const TerserPlugin = require('terser-webpack-plugin')
10 |
11 | module.exports = {
12 | devtool: 'inline-source-map',
13 | optimization: {
14 | minimizer: [
15 | new TerserPlugin({
16 | test: /vendor/,
17 | }),
18 | new TerserPlugin({
19 | test: /^((?!(vendor)).)*.js$/,
20 | })
21 | ],
22 | splitChunks: {
23 | cacheGroups: {
24 | commons: {
25 | test: /[\\/]node_modules[\\/]/,
26 | name: 'vendors',
27 | chunks: 'all'
28 | }
29 | }
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/webpack.parts.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable strict, no-console, object-shorthand, import/no-extraneous-dependencies */
6 |
7 | 'use strict'
8 |
9 | const path = require('path')
10 | const { merge } = require('webpack-merge')
11 |
12 | const development = require('./webpack.development')
13 | const production = require('./webpack.production')
14 |
15 | const AddVendorsPlugin = require('./plugins/add-vendors-plugin')
16 |
17 | const paths = {
18 | entry: path.resolve(__dirname, './src/index.js'),
19 | bundle: path.resolve(__dirname, 'dist/browser'),
20 | }
21 |
22 | const outputs = (base, env, mapping, overrides) => {
23 | const collection = []
24 | const library = 'bigchaindb-driver'
25 | const windowLibrary = 'BigchainDB'
26 |
27 | let environment = development
28 | let ext = 'js'
29 |
30 | if (env === 'production') {
31 | environment = production
32 | ext = `min.${ext}`
33 | }
34 |
35 | Object.entries(mapping).forEach(([target, extension]) => {
36 | const filename = `[name].${library}.${extension}.${ext}`
37 |
38 | const compiled = {
39 | output: {
40 | filename: filename,
41 | library: target === 'window' ? windowLibrary : library,
42 | libraryTarget: target,
43 | path: paths.bundle
44 | },
45 | plugins: [
46 | new AddVendorsPlugin(`${library}.${extension}.${ext}`)
47 | ]
48 | }
49 |
50 | collection.push(merge(base, environment, compiled, overrides))
51 | })
52 |
53 | return collection
54 | }
55 |
56 | module.exports = {
57 | outputs,
58 | paths
59 | }
60 |
--------------------------------------------------------------------------------
/webpack.production.js:
--------------------------------------------------------------------------------
1 | // Copyright BigchainDB GmbH and BigchainDB contributors
2 | // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
3 | // Code is Apache-2.0 and docs are CC-BY-4.0
4 |
5 | /* eslint-disable strict, no-console, object-shorthand */
6 |
7 | 'use strict'
8 |
9 | module.exports = {
10 | devtool: 'source-map',
11 | }
12 |
--------------------------------------------------------------------------------