Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(PE-4472): add uploadFile, uploadSignedDataItem implementations for node and web #9

Merged
merged 30 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7c454f5
feat: add uploadFiles implementation for node and web
Aug 23, 2023
56269be
feat: break services into auth vs unauth
Aug 29, 2023
254b457
chore: update examples
Aug 29, 2023
c2448fd
feat: introduce uploadSignedDataItem interface, implement for node
Aug 31, 2023
50dd308
chore: update tests and types
Aug 31, 2023
fee5675
feat: remove TurboDataItemVerifier
Sep 1, 2023
8262c90
chore: remove unused 'bundle' flag on uploadFiles, update tests to p…
Sep 1, 2023
6dc641d
chore(tests): tests should be failing, add errors to upload responses
Sep 1, 2023
b165cb5
chore: cleanup some examples and pluarlize
Sep 1, 2023
538f2f8
chore: some cleanup items
Sep 1, 2023
61c6b5f
chore: update examples, add file posting to index.cjs
Sep 1, 2023
f361dab
chore: update tests
Sep 5, 2023
1ccbbfa
fix: revert to single file upload/data item upload
Sep 5, 2023
bd4f69d
feat: abstract JWKInterface used in AuthenticatedPayment and Authenti…
Sep 5, 2023
97fd29b
fix: update web signer and cleanup examples
Sep 5, 2023
6592ac8
feat: abstract axios to TurboHTTPService class
Sep 5, 2023
8f636b1
feat: introduce AbortController
Sep 5, 2023
16ff144
chore: use inheritance for private classes
Sep 5, 2023
ebd43b3
chore: update c8 coverage files
Sep 5, 2023
e025b97
chore: add AbortController to examples
Sep 5, 2023
5c7315e
chore: add some comments and TODOs
Sep 5, 2023
6098c1a
chore: break apart tests, update config, add ReadableStream test
Sep 5, 2023
a426b08
chore: exit mocha flag to tests to avoid hanging tests involving read…
Sep 5, 2023
b308861
chore: cleanup unused utility functions
Sep 5, 2023
80fef4d
chore: fix imports of arbundles in web
Sep 5, 2023
f0a19e0
chore: update build outputs to avoid SubtleCrypto errors
Sep 5, 2023
3acba94
chore(README): add a skeleton README with placeholders for API specs
Sep 6, 2023
96208ea
chore: pull up TurboBaseFactory to common
Sep 6, 2023
b56216e
chore: cleanup comments, fix lib package outputs
Sep 6, 2023
b1559f7
chore: move from public/private factory functions to unauthenticated/…
Sep 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .c8rc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extension": [".ts"],
"include": ["src/**/*.ts"],
"exclude": ["**/*.d.ts", "**/*.test.ts"],
"exclude": ["**/*.d.ts", "**/*.test.ts", "src/types/**/*.ts"],
"all": true,
"coverage": true,
"reporter": ["text", "html"]
Expand Down
13 changes: 10 additions & 3 deletions .mocharc
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
{
"extension": ["ts"],
"spec": ["tests/**/*.test.ts", "src/**/*.test.ts"],
"require": ["ts-node/register/transpile-only"],
"extension": [
"ts"
],
"spec": [
"tests/**/*.test.ts"
],
"require": [
"ts-node/register/transpile-only",
"./mocha.setup.cjs"
],
"timeout": "10000",
"parallel": false,
"recursive": true,
Expand Down
115 changes: 113 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,114 @@
# turbo-sdk
# @ardriveapp/turbo-sdk 🚀

Hello developer, welcome to this SDK!!
Welcome to the `@ardrive/turbo-sdk`! This SDK provides functionalities for interacting with the Turbo Upload and Payment Services. It is available in both NodeJS and Web environments.

## Table of Contents

- [Installation](#installation)
- [Usage](#usage):

- [NodeJS Environments](#nodejs)
- [CommonJS](#commonjs)
- [ESM](#esm)
- [Web Environments](#web)
- [Bundlers (Webpack, Rollup, ESbuild, etc.)](#bundlers-webpack-rollup-esbuild-etc)
- [Browser](#browser)
- [Typescript](#typescript)
- [Examples](./examples)

- [Contributions](#contributions)

# Installation

```shell
npm install @ardrive/turbo-sdk
```

or

```shell
yarn add @ardrive/turbo-sdk
```

# Usage

The SDK is available in both CommonJS and ESM formats and is compatible with bundlers such as Webpack, Rollup, and ESbuild.

## Web

# Bundlers (Webpack, Rollup, ESbuild, etc.)

```javascript
import { TurboFactory } from '@ardrive/turbo-sdk/web';

const turbo = TurboFactory.unauthenticated({});
const rates = await turbo.getFiatRates();
```

### Browser

```html
<script src="https://cdn.jsdelivr.net/npm/@ardrive/turbo-sdk"></script>
<script>
const turbo = TurboFactory.unauthenticated({});
const rates = await turbo.getFiatRates();
</script>
```

## NodeJS

### CommonJS

```javascript
const { TurboFactory } = require('@ardrive/turbo-sdk/node');

const turbo = TurboFactory.unauthenticated({});
const rates = await turbo.getFiatRates();
```

### ESM

```javascript
import { TurboFactory } from '@ardrive/turbo-sdk/node';

const turbo = TurboFactory.unauthenticated({});
const rates = await turbo.getFiatRates();
```

## Typescript

The SDK provides TypeScript typings. When you import the SDK in a TypeScript project:

```typescript
import Ardrive from '@ardrive/turbo-sdk/web';

// or '@ardrive/turbo-sdk/node' for Node.js projects
```

The provided typings (`./lib/types/index.d.ts`) will be automatically recognized, offering type checking and autocompletion benefits.

# APIs (WIP)

## TurboFactory

- `public()`
- `private()`

## TurboUnauthenticatedClient

- `getFiatRates()`
- `getFiatToAR()`
- `getSupportedCountries()`
- `getSupportedCurrencies()`
- `getWincForFiat()`
- `getUploadCosts()`
- `uploadSignedDataItem()`

## TurboAuthenticatedClient

- `getBalance()`
- `uploadFile()`

# Contributions

If you encounter any issues or have feature requests, please file an issue on our GitHub repository. Contributions, pull requests, and feedback are welcome and encouraged.
3 changes: 2 additions & 1 deletion bundle.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@ const stdLibBrowser = require('node-stdlib-browser');
const bundle = async () => {
console.log('Building web bundle esm.');
const result = await build({
entryPoints: ['./src/index.ts'],
entryPoints: ['./src/web/index.ts'],
bundle: true,
platform: 'browser',
target: ['esnext'],
format: 'esm',
globalName: 'turbo',
plugins: [plugin(stdLibBrowser)],
tsconfig: './tsconfig.web.json',
outfile: './bundles/web.bundle.min.js',
inject: [require.resolve('node-stdlib-browser/helpers/esbuild/shim')],
define: {
Expand Down
Empty file added examples/node/files/0_kb.txt
Empty file.
42 changes: 34 additions & 8 deletions examples/node/index.cjs
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
const Arweave = require('arweave');
const TurboFactory = require('../../lib/index.js');

(async () => {
const { default: Arweave } = await import('arweave');
const { TurboFactory, TurboUnauthenticatedPaymentService } = await import(
'../../lib/node/index.js'
);
const path = require('path');
const fs = require('fs');
/**
* Fetching rates using an unauthenticated Turbo client.
*/
const turbo = TurboFactory.init();
const rates = await turbo.getRates();
const turbo = TurboFactory.unauthenticated();
const rates = await turbo.getFiatRates();
console.log('Fetched rates:', JSON.stringify(rates, null, 2));

/**
* Alternatively instantiate your own clients independently.
*/
const paymentService = new TurboUnauthenticatedPaymentService({
url: 'https://payment.ardrive.dev',
});
const supportedCurrencies = await paymentService.getSupportedCurrencies();
console.log(
'Supported currencies:',
JSON.stringify(supportedCurrencies, null, 2),
);

/**
* Create a new arweave private key
*/
const arweave = Arweave.init();
const arweave = new Arweave({});
const jwk = await Arweave.crypto.generateJWK();
const address = await arweave.wallets.jwkToAddress(jwk);

/**
* Use the arweave key to create an authenticated turbo client
*/
const turboAuthClient = TurboFactory.init({ privateKey: jwk });
const turboAuthClient = TurboFactory.authenticated({ privateKey: jwk });

/**
* Fetch the balance for the private key.
Expand All @@ -38,11 +53,22 @@ const TurboFactory = require('../../lib/index.js');
);

/**
* Fetch the estimated amount of winc returned for $1 USD
* Fetch the estimated amount of winc returned for 10 USD (1000 cents).
*/
const estimatedWinc = await turboAuthClient.getWincForFiat({
amount: 1000,
currency: 'usd',
});
console.log('10 USD to winc:', estimatedWinc);

/**
* Post local files to the Turbo service.
*/
console.log('Posting raw file to Turbo service...');
const filePath = path.join(__dirname, './files/0_kb.txt');
const uploadResult = await turboAuthClient.uploadFile({
fileStreamFactory: () => fs.createReadStream(filePath),
signal: AbortSignal.timeout(10_000), // cancel the upload after 10 seconds
});
console.log(JSON.stringify(uploadResult, null, 2));
})();
37 changes: 32 additions & 5 deletions examples/node/index.mjs
Original file line number Diff line number Diff line change
@@ -1,22 +1,38 @@
import Arweave from 'arweave';
import fs from 'fs';

import { TurboFactory } from '../../lib/index.js';
import {
TurboFactory,
TurboUnauthenticatedPaymentService,
} from '../../lib/node/index.js';

(async () => {
/**
* Fetching rates using an unauthenticated Turbo client.
*/
const turbo = TurboFactory.init();
const turbo = TurboFactory.unauthenticated();
const rates = await turbo.getFiatRates();
console.log('Fetched rates:', JSON.stringify(rates, null, 2));

/*
* Alternatively instantiate your own clients independently.
*/
const paymentService = new TurboUnauthenticatedPaymentService({
url: 'https://payment.ardrive.dev',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing down some aside thoughts on exposing our ArDrive Turbo "testnet"

This public test API (payment.ardrive.dev / upload.ardrive.dev):

  • will accept Stripe Test Cards to reward Credits
  • sends data to a live production gateway (arweave.net)
  • posts optical bridge GQL info to prod gateway (arweave.net)
  • has an optimistic data cache with dev gateway (arweave.dev)
  • also accepts free data under 500 KiB

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel our testnet could offer developers great advantages during building. But our test data should expire and never make it to a live arweave node

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed - we may need to consider a separate public test environment that is low-cost for us but dev friendly

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also a good point to provide some testing utils and constants to help devs write unit tests with the SDK (e.g. test card numbers)

});
const supportedCurrencies = await paymentService.getSupportedCurrencies();
console.log(
'Supported currencies:',
JSON.stringify(supportedCurrencies, null, 2),
);

/**
* Fetching balance using an authenticated Turbo client.
*/
const arweave = Arweave.init();
const arweave = new Arweave.init();
const jwk = await Arweave.crypto.generateJWK();
const address = await arweave.wallets.jwkToAddress(jwk);
const turboAuthClient = TurboFactory.init({ privateKey: jwk });
const turboAuthClient = TurboFactory.authenticated({ privateKey: jwk });
const balance = await turboAuthClient.getBalance();
console.log(
'Balance:',
Expand All @@ -31,11 +47,22 @@ import { TurboFactory } from '../../lib/index.js';
);

/**
* Fetch the estimated amount of winc returned for $1 USD
* Fetch the estimated amount of winc returned for 10 USD (1000 cents).
*/
const estimatedWinc = await turboAuthClient.getWincForFiat({
amount: 1000,
currency: 'usd',
});
console.log('10 USD to winc:', estimatedWinc);

/**
* Post local files to the Turbo service.
*/
console.log('Posting raw files to Turbo service...');
const filePath = new URL('files/0_kb.txt', import.meta.url).pathname;
const uploadResult = await turboAuthClient.uploadFile({
fileStreamFactory: () => fs.createReadStream(filePath),
signal: AbortSignal.timeout(10_000), // cancel the upload after 10 second
});
console.log(JSON.stringify(uploadResult, null, 2));
})();
Loading