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: GraphQL subscriptions #1374

Merged
merged 77 commits into from
Dec 20, 2023
Merged
Show file tree
Hide file tree
Changes from 74 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
7df5b6f
checkpoint
nedsalk Oct 20, 2023
faf16fb
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Oct 22, 2023
a1a4567
mostly implemented subscriptions
nedsalk Oct 23, 2023
a6f3a74
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Oct 23, 2023
450cfef
checkpoint
nedsalk Oct 24, 2023
c34c3b7
feat: subscriptions work
nedsalk Oct 25, 2023
8f66eff
test: moved tests
nedsalk Oct 25, 2023
abb2085
refactor: to use async/await a bit more
nedsalk Oct 25, 2023
b9517c6
refactor: some more
nedsalk Oct 25, 2023
a9ddb66
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Oct 25, 2023
3626eeb
chore: updated nodejs version
nedsalk Oct 25, 2023
305baee
feat: ability to set timeout
nedsalk Oct 25, 2023
30357b6
fix explanation
nedsalk Oct 25, 2023
dda0fae
refactor: variable use
nedsalk Oct 25, 2023
5239058
test: better naming
nedsalk Oct 25, 2023
06d58cd
test: enable test
nedsalk Oct 25, 2023
4420a43
removed unnecessary keepalive (set by server)
nedsalk Oct 25, 2023
77cfe16
chore: changeset
nedsalk Oct 25, 2023
4989346
revert settings.json
nedsalk Oct 25, 2023
75eedea
refactor: use pipeThrough with custom TransformStream
nedsalk Oct 25, 2023
1cf4339
refactor: types
nedsalk Oct 25, 2023
268088a
refactor: naming
nedsalk Oct 25, 2023
620de31
refactor: ternary operator ftw
nedsalk Oct 25, 2023
8d46b15
refactor: omit fetch from options passed to custom fetch
nedsalk Oct 25, 2023
6368f21
test: explanations
nedsalk Oct 25, 2023
40e0dba
refactor: var name
nedsalk Oct 25, 2023
291c52a
Merge branch 'master' into ns/feat/subscriptions
nedsalk Oct 26, 2023
a8a3d96
Merge branch 'master' into ns/feat/subscriptions
nedsalk Oct 27, 2023
5b1a4ea
Merge branch 'master' into ns/feat/subscriptions
nedsalk Oct 30, 2023
a358e3e
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Nov 3, 2023
9c086f6
chore: update all packages to use node v18.18.2
nedsalk Nov 3, 2023
ec38716
set node-version to correct in test-setup action
nedsalk Nov 3, 2023
99e0982
lint: removed unused variables
nedsalk Nov 3, 2023
75f07b8
Merge branch 'master' into ns/feat/subscriptions
nedsalk Nov 4, 2023
9db66f6
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Nov 7, 2023
087d6a4
Merge branch 'master' into ns/feat/subscriptions
nedsalk Nov 7, 2023
8a5ced3
Merge branch 'master' into ns/feat/subscriptions
nedsalk Nov 7, 2023
cd092d9
Merge branch 'master' into ns/feat/subscriptions
nedsalk Nov 8, 2023
5abb882
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Nov 8, 2023
66ed475
chore: update all packages to 18.18.2 again
nedsalk Nov 8, 2023
1ff19c0
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Nov 10, 2023
9c88403
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Nov 11, 2023
dfe679a
refactor: change loop style
nedsalk Nov 13, 2023
bb7ea51
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Nov 13, 2023
0dc0c9e
Merge branch 'master' into ns/feat/subscriptions
nedsalk Nov 13, 2023
f9e41fb
Merge branch 'master' into ns/feat/subscriptions
nedsalk Nov 14, 2023
56fea7e
Merge branch 'master' into ns/feat/subscriptions
nedsalk Nov 15, 2023
ab7772e
fix: linting and formatting
nedsalk Nov 20, 2023
890db10
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Nov 20, 2023
b67fef0
Merge remote-tracking branch 'origin/master' into ns/feat/subscriptions
nedsalk Dec 2, 2023
7a2bece
Merge remote-tracking branch 'origin/rc/salamander' into ns/feat/subs…
nedsalk Dec 13, 2023
7184f6d
Merge branch 'rc/salamander' into ns/feat/subscriptions
nedsalk Dec 13, 2023
70174b5
Merge branch 'rc/salamander' into ns/feat/subscriptions
nedsalk Dec 14, 2023
16d29ba
Merge branch 'rc/salamander' into ns/feat/subscriptions
nedsalk Dec 14, 2023
2ef9905
Merge branch 'rc/salamander' into ns/feat/subscriptions
nedsalk Dec 15, 2023
52ed445
Merge branch 'rc/salamander' into ns/feat/subscriptions
nedsalk Dec 15, 2023
9f180fb
refactor: createOperations
nedsalk Dec 15, 2023
8a73bc8
fix: shorten poa-interval-period
nedsalk Dec 15, 2023
61d8d9c
Merge branch 'rc/salamander' into ns/feat/subscriptions
nedsalk Dec 15, 2023
6022a55
fix: linting
nedsalk Dec 15, 2023
97ed06a
Merge branch 'ns/feat/subscriptions' of github.com:FuelLabs/fuels-ts …
nedsalk Dec 15, 2023
3e6cfca
fix: shouldn't be async
nedsalk Dec 16, 2023
6e451e4
fix: prefix unused variable with underscore
nedsalk Dec 16, 2023
06a1200
removed no-unused-vars exception for variables
nedsalk Dec 16, 2023
aa3e80f
refactor: reduce nesting for subscription types
nedsalk Dec 16, 2023
94afc36
refactor: remove ts-ignores
nedsalk Dec 16, 2023
376995d
fix: mocks not compiling
nedsalk Dec 16, 2023
6d4d228
Revert "refactor: reduce nesting for subscription types"
nedsalk Dec 17, 2023
f2dfdde
refactor: into `subscription` variable
nedsalk Dec 17, 2023
3bc4325
lower --poa to 3s
nedsalk Dec 17, 2023
b780989
test: better assertion
nedsalk Dec 17, 2023
8e26878
test: better assertion
nedsalk Dec 17, 2023
37e816a
Merge branch 'ns/feat/subscriptions' of github.com:FuelLabs/fuels-ts …
nedsalk Dec 18, 2023
e527956
Merge branch 'rc/salamander' into ns/feat/subscriptions
nedsalk Dec 18, 2023
70e11f3
Update packages/providers/test/provider.test.ts
nedsalk Dec 19, 2023
2852da1
Merge branch 'rc/salamander' into ns/feat/subscriptions
nedsalk Dec 19, 2023
2f6f236
Merge branch 'rc/salamander' into ns/feat/subscriptions
nedsalk Dec 19, 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
6 changes: 6 additions & 0 deletions .changeset/serious-laws-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@fuel-ts/providers": minor
"@fuel-ts/errors": patch
---

Implemented GraphQL subscriptions
7 changes: 6 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ module.exports = {
},
},
rules: {
'no-restricted-syntax': [
'off',
{
selector: 'ForOfStatement',
arboleya marked this conversation as resolved.
Show resolved Hide resolved
},
],
'@typescript-eslint/no-non-null-assertion': 1,
// Disable error on devDependencies importing since this isn't a TS library
'import/no-extraneous-dependencies': ['error', { devDependencies: true }],
Expand Down Expand Up @@ -56,7 +62,6 @@ module.exports = {
'warn',
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
},
],
'@typescript-eslint/no-explicit-any': 'error',
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/ci-setup/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: "CI Setup"
inputs:
node-version:
description: "Node version"
default: 18.14.1
default: 18.18.2
pnpm-version:
description: "PNPM version"
default: 8.9.0
Expand Down
4 changes: 2 additions & 2 deletions .github/actions/test-setup/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: "Test Setup"
inputs:
node-version:
description: "Node version"
default: 18.14.1
default: 18.18.2
pnpm-version:
description: "PNPM version"
default: 8.9.0
Expand Down Expand Up @@ -31,4 +31,4 @@ runs:

- name: Build
run: pnpm build
shell: bash
shell: bash
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.14.1
18.18.2
7 changes: 1 addition & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"author": "Fuel Labs <[email protected]> (https://fuel.network/)",
"private": true,
"engines": {
"node": "^18.14.1",
"node": "^18.18.2",
nedsalk marked this conversation as resolved.
Show resolved Hide resolved
"pnpm": "^8.9.0"
},
"packageManager": "[email protected]",
Expand Down Expand Up @@ -91,10 +91,5 @@
"tsx": "^3.12.7",
"turbo": "^1.8.8",
"typescript": "~5.2.2"
},
"pnpm": {
"overrides": {
"cross-fetch": "4.0.0"
}
}
}
2 changes: 1 addition & 1 deletion packages/abi-coder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/abi-typegen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/address/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/contract/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/crypto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"browser": {
"./dist/index.mjs": "./dist/index.browser.mjs"
Expand Down
2 changes: 1 addition & 1 deletion packages/errors/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
1 change: 1 addition & 0 deletions packages/errors/src/error-codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export enum ErrorCode {
CONVERTING_FAILED = 'converting-error',
ELEMENT_NOT_FOUND = 'element-not-found',
MISSING_REQUIRED_PARAMETER = 'missing-required-parameter',
INVALID_REQUEST = 'invalid-request',
UNEXPECTED_HEX_VALUE = 'unexpected-hex-value',

// transaction
Expand Down
38 changes: 27 additions & 11 deletions packages/fuel-gauge/src/transaction-response.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { generateTestWallet } from '@fuel-ts/wallet/test-utils';
import type { BN, WalletUnlocked } from 'fuels';
import { BaseAssetId, FUEL_NETWORK_URL, Provider, TransactionResponse, Wallet } from 'fuels';
import { generateTestWallet, launchNode } from '@fuel-ts/wallet/test-utils';
import type { BN } from 'fuels';
import {
BaseAssetId,
FUEL_NETWORK_URL,
Provider,
TransactionResponse,
Wallet,
randomBytes,
WalletUnlocked,
} from 'fuels';

describe('TransactionSummary', () => {
let provider: Provider;
Expand Down Expand Up @@ -75,25 +83,33 @@ describe('TransactionSummary', () => {
});

it('should ensure waitForResult always waits for the transaction to be processed', async () => {
const destination = Wallet.generate({
provider,
const { cleanup, ip, port } = await launchNode({
args: ['--poa-interval-period', '750ms'],
});
const nodeProvider = await Provider.create(`http://${ip}:${port}/graphql`);

const { id: transactionId } = await adminWallet.transfer(
const genesisWallet = new WalletUnlocked(
process.env.GENESIS_SECRET || randomBytes(32),
nodeProvider
);

const destination = Wallet.generate({ provider: nodeProvider });

const { id: transactionId } = await genesisWallet.transfer(
destination.address,
100,
BaseAssetId,
{ gasPrice, gasLimit: 10_000 }
);
const response = await TransactionResponse.create(transactionId, nodeProvider);

const response = new TransactionResponse(transactionId, provider);

expect(response.gqlTransaction).toBeUndefined();
expect(response.gqlTransaction?.status?.type).toBe('SubmittedStatus');

await response.waitForResult();

expect(response.gqlTransaction?.status?.type).toBeDefined();
expect(response.gqlTransaction?.status?.type).not.toEqual('SubmittedStatus');
expect(response.gqlTransaction?.status?.type).toEqual('SuccessStatus');
expect(response.gqlTransaction?.id).toBe(transactionId);

cleanup();
});
});
2 changes: 1 addition & 1 deletion packages/fuels/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/hasher/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/hdwallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/interfaces/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/math/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/merkle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/mnemonic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/predicate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/program/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down
2 changes: 1 addition & 1 deletion packages/providers/codegen.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"plugins": [
{ "typescript": {} },
{ "typescript-operations": {} },
{ "typescript-graphql-request": {} }
{ "typescript-generic-sdk": {} }
],
"config": {
"scalars": {
Expand Down
8 changes: 4 additions & 4 deletions packages/providers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"engines": {
"node": "^18.14.1"
"node": "^18.18.2"
},
"exports": {
".": {
Expand Down Expand Up @@ -48,9 +48,9 @@
"@fuel-ts/utils": "workspace:*",
"@graphql-codegen/cli": "^2.13.7",
"@graphql-codegen/typescript": "^2.8.0",
"@graphql-codegen/typescript-graphql-request": "^4.5.7",
"@graphql-codegen/typescript-operations": "^2.5.5",
"@types/ramda": "^0.29.3",
"get-graphql-schema": "^2.1.2"
"@graphql-codegen/typescript-generic-sdk": "^3.1.0",
arboleya marked this conversation as resolved.
Show resolved Hide resolved
"get-graphql-schema": "^2.1.2",
"@types/ramda": "^0.29.3"
}
}
81 changes: 81 additions & 0 deletions packages/providers/src/fuel-graphql-subscriber.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { FuelError } from '@fuel-ts/errors';
import type { DocumentNode } from 'graphql';
import { print } from 'graphql';

type FuelGraphQLSubscriberOptions = {
url: string;
query: DocumentNode;
variables?: Record<string, unknown>;
fetchFn: typeof fetch;
abortController?: AbortController;
};

class FuelSubscriptionStream implements TransformStream {
readable: ReadableStream<FuelError | Record<string, unknown>>;
writable: WritableStream<Uint8Array>;
private readableStreamController!: ReadableStreamController<FuelError | Record<string, unknown>>;
private static textDecoder = new TextDecoder();

constructor() {
this.readable = new ReadableStream({
start: (controller) => {
this.readableStreamController = controller;
},
});

this.writable = new WritableStream<Uint8Array>({
write: (bytes) => {
const text = FuelSubscriptionStream.textDecoder.decode(bytes);
// the fuel node sends keep-alive messages that should be ignored
if (text.startsWith('data:')) {
const { data, errors } = JSON.parse(text.split('data:')[1]);
if (Array.isArray(errors)) {
this.readableStreamController.enqueue(
new FuelError(
FuelError.CODES.INVALID_REQUEST,
errors.map((err) => err.message).join('\n\n')
)
);
} else {
this.readableStreamController.enqueue(data);
}
}
},
});
}
}

export async function* fuelGraphQLSubscriber({
url,
variables,
query,
fetchFn,
}: FuelGraphQLSubscriberOptions) {
const response = await fetchFn(`${url}-sub`, {
method: 'POST',
body: JSON.stringify({
query: print(query),
variables,
}),
headers: {
'Content-Type': 'application/json',
Accept: 'text/event-stream',
},
});

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const subscriptionStreamReader = response
.body!.pipeThrough(new FuelSubscriptionStream())
.getReader();
Torres-ssf marked this conversation as resolved.
Show resolved Hide resolved

while (true) {
const { value, done } = await subscriptionStreamReader.read();
if (value instanceof FuelError) {
throw value;
}
yield value;
nedsalk marked this conversation as resolved.
Show resolved Hide resolved
nedsalk marked this conversation as resolved.
Show resolved Hide resolved
if (done) {
break;
}
}
}
Loading
Loading