issue-166-open-timestamps #220
@ -6,7 +6,7 @@ module.exports = {
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended'
|
||||
],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs', 'licenseChecker.cjs'],
|
||||
ignorePatterns: ['dist', '.eslintrc.cjs', 'licenseChecker.cjs', "*.min.js"],
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['react-refresh'],
|
||||
rules: {
|
||||
|
@ -8,6 +8,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="/opentimestamps.min.js"></script>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
2
public/opentimestamps.min.js
vendored
Normal file
2
public/opentimestamps.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
28
src/types/opentimestamps.d.ts
vendored
Normal file
28
src/types/opentimestamps.d.ts
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
interface OpenTimestamps {
|
||||
// Create a detached timestamp file from a buffer or file hash
|
||||
DetachedTimestampFile: {
|
||||
fromHash(op: any, hash: Uint8Array): any
|
||||
}
|
||||
|
||||
// Stamp the provided timestamp file and return a Promise
|
||||
stamp(file: any): Promise<void>
|
||||
|
||||
// Verify the provided timestamp proof file
|
||||
verify(file: any): Promise<void>
|
||||
|
||||
// Other utilities or operations (like OpSHA256, serialization)
|
||||
Ops: {
|
||||
OpSHA256: any
|
||||
OpSHA1?: any
|
||||
}
|
||||
|
||||
Context: {
|
||||
StreamSerialization: any
|
||||
}
|
||||
|
||||
// Load a timestamp file from a buffer
|
||||
deserialize(bytes: Uint8Array): any
|
||||
|
||||
// Other potential methods based on repo functions
|
||||
upgrade(file: any): Promise<void>
|
||||
}
|
1
src/types/system/index.d.ts
vendored
1
src/types/system/index.d.ts
vendored
@ -3,5 +3,6 @@ import type { WindowNostr } from 'nostr-tools/nip07'
|
||||
declare global {
|
||||
interface Window {
|
||||
nostr?: WindowNostr
|
||||
OpenTimestamps: OpenTimestamps
|
||||
}
|
||||
}
|
||||
|
39
src/utils/opentimestamps.ts
Normal file
39
src/utils/opentimestamps.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { Timestamp } from '../types'
|
||||
import { isPromiseFulfilled } from './utils.ts'
|
||||
import { retryAll } from './retry.ts'
|
||||
import { bytesToHex, hexToBytes } from '@noble/hashes/utils'
|
||||
|
||||
/**
|
||||
* Generates a timestamp for the provided document hashes.
|
||||
* @returns Timestamp in a hex string format
|
||||
*/
|
||||
export const generateTimestamps = async (
|
||||
fileHashes: string[]
|
||||
): Promise<Timestamp[] | undefined> => {
|
||||
const promises = fileHashes.map((fileHash) => () => timestamp(fileHash))
|
||||
const resolvedPromises = await retryAll(promises)
|
||||
if (resolvedPromises.every(isPromiseFulfilled)) {
|
||||
return resolvedPromises.map(({ value }, index) => {
|
||||
return {
|
||||
fileHash: fileHashes[index],
|
||||
timestamp: value
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const timestamp = async (hash: string) => {
|
||||
const detachedTimestamp =
|
||||
window.OpenTimestamps.DetachedTimestampFile.fromHash(
|
||||
new window.OpenTimestamps.Ops.OpSHA256(),
|
||||
hexToBytes(hash)
|
||||
)
|
||||
|
||||
await window.OpenTimestamps.stamp(detachedTimestamp)
|
||||
const ctx = new window.OpenTimestamps.Context.StreamSerialization()
|
||||
detachedTimestamp.serialize(ctx)
|
||||
const timestampBytes = ctx.getOutput()
|
||||
const hex = bytesToHex(timestampBytes)
|
||||
|
||||
return hex
|
||||
}
|
25
src/utils/retry.ts
Normal file
25
src/utils/retry.ts
Normal file
@ -0,0 +1,25 @@
|
||||
export const retryAll = async <T>(
|
||||
promises: (() => Promise<T>)[],
|
||||
retries: number = 3,
|
||||
delay: number = 1000
|
||||
) => {
|
||||
const wrappedPromises = promises.map((fn) => retry(fn, retries, delay))
|
||||
return Promise.allSettled(wrappedPromises)
|
||||
}
|
||||
|
||||
export const retry = async <T>(
|
||||
fn: () => Promise<T>,
|
||||
retries: number = 3,
|
||||
delay: number = 1000
|
||||
): Promise<T> => {
|
||||
try {
|
||||
return await fn()
|
||||
} catch (err) {
|
||||
if (retries === 0) {
|
||||
return Promise.reject(err)
|
||||
}
|
||||
return new Promise((resolve) =>
|
||||
setTimeout(() => resolve(retry(fn, retries - 1)), delay)
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user