-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(inital providers): scaffold initial providers
- Loading branch information
1 parent
6969d3a
commit 4949514
Showing
19 changed files
with
915 additions
and
2,133 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,3 +4,4 @@ lib | |
**/*.cjs | ||
**/*.mjs | ||
examples | ||
jest.config.ts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
/** | ||
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
import Arweave from 'arweave'; | ||
import fetchBuilder from 'fetch-retry'; | ||
|
||
import { IContractStateProvider } from '../types.js'; | ||
|
||
export class ArIoError extends Error { | ||
constructor(message: string) { | ||
super(message); | ||
this.name = 'ArIoError'; | ||
} | ||
} | ||
|
||
export class ArIo implements IContractStateProvider { | ||
_arweave: Arweave; | ||
_contractStateProviders: IContractStateProvider[]; | ||
http: typeof fetch; | ||
log: (message: string) => void; | ||
|
||
constructor({ | ||
arweave, | ||
contractStateProviders, | ||
logger, | ||
}: { | ||
arweave?: Arweave; | ||
contractStateProviders: IContractStateProvider[]; | ||
logger?: (message: string) => void; | ||
}) { | ||
this._arweave = arweave ?? Arweave.init({}); // use default arweave instance if not provided | ||
this._contractStateProviders = contractStateProviders; | ||
this.http = fetchBuilder(fetch, { | ||
retries: 3, | ||
retryDelay: 2000, | ||
retryOn: [429, 500, 502, 503, 504], | ||
}); | ||
this.log = | ||
logger ?? | ||
((message: string) => { | ||
console.debug(`[ArIo Client]: ${message}`); | ||
}); | ||
} | ||
|
||
/** | ||
* Fetches the state of a contract from the Arweave network. | ||
* @param contractId - The contract ID to fetch the state for. | ||
* @param strategy - The strategy to use when fetching the state - 'race', 'compare', or 'fallback'. | ||
* - 'race' will call each provider and return the first result. | ||
* - 'compare' will call each provider and return the result that has the highest blockheight evaluated. | ||
* - 'fallback' will call first remote providers, then gql providers if remote fetch failed. | ||
* @returns The state of the contract. | ||
* | ||
* @example | ||
* const state = await ario.getContractState('contractId', 'fallback'); | ||
*/ | ||
async getContractState<ContractState>( | ||
contractId: string, | ||
strategy: 'race' | 'compare' | 'fallback' = 'race', | ||
): Promise<ContractState> { | ||
this.log( | ||
`Fetching contract state for contract [${contractId}] using a ${strategy} strategy `, | ||
); | ||
switch (strategy) { | ||
case 'race': | ||
return Promise.race( | ||
this._contractStateProviders.map((provider) => | ||
provider.getContractState<ContractState>(contractId), | ||
), | ||
); | ||
case 'compare': | ||
// TODO: implement compare strategy | ||
throw new Error('Not implemented'); | ||
case 'fallback': | ||
// TODO: implement fallback strategy | ||
throw new Error('Not implemented'); | ||
default: { | ||
const message = `Invalid strategy provided for contract [${contractId}]: ${strategy}`; | ||
this.log(message); | ||
throw new ArIoError(message); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/** | ||
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
import fetchBuilder from 'fetch-retry'; | ||
|
||
import { IContractStateProvider } from '../../types.js'; | ||
import { validateArweaveId } from '../../utils/index.js'; | ||
|
||
export class ArNSRemoteCacheError extends Error { | ||
constructor(message: string) { | ||
super(message); | ||
this.name = 'ArNSRemoteCacheError'; | ||
} | ||
} | ||
|
||
/** | ||
* ArNSRemoteCache class implements the IContractStateProvider interface. | ||
* It provides methods to interact with a remote ArNS SmartWeave State Evaluator. | ||
* | ||
* @property {string} remoteCacheUrl - The URL of the remote cache. Defaults to 'api.arns.app'. | ||
* @property {string} apiVersion - The API version to use for the remote cache. Defaults to 'v1'. | ||
* @property {(message: string) => void} log - A logging function. If not provided, it defaults to a function that logs debug messages to the console. | ||
* @property {typeof fetch} http - A fetch function with retry capabilities. | ||
* @property {Object} httpOptions - Options to pass to the fetch function. | ||
* | ||
* @example | ||
* const cache = new ArNSRemoteCache({}) || new ArNSRemoteCache({ | ||
* url: 'https://example.com/cache', | ||
* logger: message => console.log(`Custom logger: ${message}`), | ||
* version: 'v1', | ||
* httpOptions: { | ||
* retries: 3, | ||
* retryDelay: 2000, | ||
* retryOn: [404, 429, 503], | ||
* }, | ||
* }); | ||
*/ | ||
export class ArNSRemoteCache implements IContractStateProvider { | ||
remoteCacheUrl: string; | ||
apiVersion: string; | ||
log: (message: string) => void; | ||
http: typeof fetch; | ||
constructor({ | ||
url = 'api.arns.app', | ||
logger, | ||
version = 'v1', | ||
httpOptions = { | ||
retries: 3, | ||
retryDelay: 2000, | ||
retryOn: [404, 429, 503], | ||
}, | ||
}: { | ||
url?: string; | ||
logger?: (message: string) => void; | ||
version?: string; | ||
httpOptions?: Parameters<typeof fetchBuilder>[1]; | ||
}) { | ||
this.remoteCacheUrl = url; | ||
this.apiVersion = version; | ||
this.log = | ||
logger ?? | ||
((message: string) => { | ||
console.debug(`[ArNS Remote Cache]: ${message}`); | ||
}); | ||
this.http = fetchBuilder(fetch, httpOptions); | ||
} | ||
|
||
/** | ||
* Fetches the state of a contract from the remote cache. | ||
* @param {string} contractId - The Arweave transaction id of the contract. | ||
*/ | ||
async getContractState<ContractState>( | ||
contractId: string, | ||
): Promise<ContractState> { | ||
validateArweaveId(contractId); | ||
|
||
this.log(`Fetching contract state for [${contractId}]`); | ||
|
||
const response = await this.http( | ||
`${this.remoteCacheUrl}/${this.apiVersion}/contract/${contractId}`, | ||
).catch((error) => { | ||
const message = `Failed to fetch contract state for [${contractId}]: ${error}`; | ||
|
||
this.log(message); | ||
|
||
throw new ArNSRemoteCacheError(message); | ||
}); | ||
|
||
this.log( | ||
`Fetched contract state for [${contractId}]. State size: ${response.headers.get('content-length')} bytes.`, | ||
); | ||
|
||
return response.json(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
export * from './ArIo.js'; | ||
export * from './ContractStateProviders/index.js'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
export const ARWEAVE_TX_REGEX = new RegExp('^[a-zA-Z0-9_-]{43}$'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
export * from '../types.js'; | ||
export * from '../common/index.js'; | ||
export * from '../constants.js'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
export interface IContractStateProvider { | ||
/** | ||
* The ContractStateProvider interface is used to define a contract state provider. | ||
*/ | ||
getContractState<T>(contractId: string): Promise<T>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
import { ARWEAVE_TX_REGEX } from '../constants.js'; | ||
|
||
export const validateArweaveId = (id: string): void => { | ||
if (!ARWEAVE_TX_REGEX.test(id)) { | ||
throw new Error( | ||
`Invalid contract id: [${id}]. Must be a valid Arweave transaction id.`, | ||
); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/** | ||
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
export * from './arweave.js'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/** | ||
* Copyright (C) 2022-2024 Permanent Data Solutions, Inc. All Rights Reserved. | ||
* | ||
* This program is free software: you can redistribute it and/or modify | ||
* it under the terms of the GNU Affero General Public License as published by | ||
* the Free Software Foundation, either version 3 of the License, or | ||
* (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Affero General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Affero General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
export * from '../types.js'; | ||
export * from '../common/index.js'; | ||
export * from '../constants.js'; |
Oops, something went wrong.