wao 0.29.1 → 0.29.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/devs.js +122 -110
- package/cjs/encode.js +4 -24
- package/cjs/hb.js +1 -3
- package/cjs/httpsig.js +51 -17
- package/cjs/hyperbeam.js +1 -0
- package/cjs/send.js +1 -7
- package/cjs/signer.js +148 -116
- package/cjs/workspace/package.json +1 -1
- package/esm/devs.js +56 -33
- package/esm/encode.js +2 -5
- package/esm/hb.js +1 -1
- package/esm/httpsig.js +39 -17
- package/esm/hyperbeam.js +1 -1
- package/esm/send.js +1 -7
- package/esm/signer.js +72 -76
- package/esm/workspace/package.json +1 -1
- package/package.json +1 -1
package/esm/send.js
CHANGED
|
@@ -10,8 +10,6 @@ const {
|
|
|
10
10
|
import { from } from "./httpsig.js"
|
|
11
11
|
|
|
12
12
|
export async function send(signedMsg, fetchImpl = fetch) {
|
|
13
|
-
// IMPORTANT: Use the URL from signedMsg.url, NOT from any path header
|
|
14
|
-
// This ensures we send to the correct URL even if path header is different
|
|
15
13
|
const fetchOptions = {
|
|
16
14
|
method: signedMsg.method,
|
|
17
15
|
headers: signedMsg.headers,
|
|
@@ -25,7 +23,6 @@ export async function send(signedMsg, fetchImpl = fetch) {
|
|
|
25
23
|
fetchOptions.body = signedMsg.body
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
// Use the URL as provided, ignoring any path header
|
|
29
26
|
const response = await fetchImpl(signedMsg.url, fetchOptions)
|
|
30
27
|
if (response.status >= 400) {
|
|
31
28
|
throw new Error(`${response.status}: ${await response.text()}`)
|
|
@@ -36,10 +33,7 @@ export async function send(signedMsg, fetchImpl = fetch) {
|
|
|
36
33
|
response.headers.forEach((v, k) => (headers[k] = v))
|
|
37
34
|
} else headers = response.headers
|
|
38
35
|
const http = { headers, body: await response.text(), status: response.status }
|
|
39
|
-
return {
|
|
40
|
-
out: from(http),
|
|
41
|
-
...http,
|
|
42
|
-
}
|
|
36
|
+
return { ...from(http), ...http }
|
|
43
37
|
}
|
|
44
38
|
|
|
45
39
|
const httpSigName = address => {
|
package/esm/signer.js
CHANGED
|
@@ -1,97 +1,93 @@
|
|
|
1
1
|
import { toHttpSigner } from "./send.js"
|
|
2
2
|
import { enc } from "./encode.js"
|
|
3
|
+
import { createSigner } from "@permaweb/aoconnect"
|
|
3
4
|
|
|
4
5
|
const joinUrl = ({ url, path }) => {
|
|
5
|
-
if (path.startsWith("http://") || path.startsWith("https://"))
|
|
6
|
-
return path
|
|
7
|
-
}
|
|
8
|
-
// Ensure path starts with /
|
|
6
|
+
if (path.startsWith("http://") || path.startsWith("https://")) return path
|
|
9
7
|
const normalizedPath = path.startsWith("/") ? path : "/" + path
|
|
10
8
|
return url.endsWith("/")
|
|
11
9
|
? url.slice(0, -1) + normalizedPath
|
|
12
10
|
: url + normalizedPath
|
|
13
11
|
}
|
|
14
12
|
|
|
15
|
-
export function
|
|
16
|
-
const
|
|
13
|
+
export async function sign({ url, path, msg: encoded, jwk, signPath = false }) {
|
|
14
|
+
const signer = createSigner(jwk, url)
|
|
15
|
+
const { body = null, ...headers } = encoded
|
|
16
|
+
let _enc = { headers }
|
|
17
|
+
if (body) _enc.body = new Blob([body])
|
|
18
|
+
return await _sign({ signer, encoded: _enc, url, path, _path: signPath })
|
|
19
|
+
}
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
async function _sign({
|
|
22
|
+
encoded,
|
|
23
|
+
signer,
|
|
24
|
+
path,
|
|
25
|
+
url,
|
|
26
|
+
method = "POST",
|
|
27
|
+
_path = false,
|
|
28
|
+
}) {
|
|
29
|
+
const headersObj = encoded ? encoded.headers : {}
|
|
30
|
+
const body = encoded ? encoded.body : undefined
|
|
31
|
+
const _url = joinUrl({ url, path })
|
|
32
|
+
headersObj["path"] = path
|
|
33
|
+
if (body && !headersObj["content-length"]) {
|
|
34
|
+
const bodySize = body.size || body.byteLength || 0
|
|
35
|
+
if (bodySize > 0) headersObj["content-length"] = String(bodySize)
|
|
36
|
+
}
|
|
37
|
+
const lowercaseHeaders = {}
|
|
38
|
+
for (const [key, value] of Object.entries(headersObj)) {
|
|
39
|
+
lowercaseHeaders[key.toLowerCase()] = value
|
|
40
|
+
}
|
|
41
|
+
const bodyKeys = headersObj["body-keys"]
|
|
42
|
+
? headersObj["body-keys"]
|
|
43
|
+
.replace(/"/g, "")
|
|
44
|
+
.split(",")
|
|
45
|
+
.map(k => k.trim())
|
|
46
|
+
: []
|
|
47
|
+
|
|
48
|
+
const signingFields = Object.keys(lowercaseHeaders).filter(
|
|
49
|
+
key => key !== "body-keys" && key !== "path" && !bodyKeys.includes(key)
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
if (_path) signingFields.push("path")
|
|
53
|
+
|
|
54
|
+
if (signingFields.length === 0 && !body) {
|
|
55
|
+
lowercaseHeaders["content-length"] = "0"
|
|
56
|
+
signingFields.push("content-length")
|
|
20
57
|
}
|
|
21
58
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const headersObj = encoded ? encoded.headers : {}
|
|
27
|
-
const body = encoded ? encoded.body : undefined
|
|
28
|
-
|
|
29
|
-
const _url = joinUrl({ url, path })
|
|
30
|
-
|
|
31
|
-
headersObj["path"] = path
|
|
32
|
-
|
|
33
|
-
if (body && !headersObj["content-length"]) {
|
|
34
|
-
const bodySize = body.size || body.byteLength || 0
|
|
35
|
-
if (bodySize > 0) {
|
|
36
|
-
headersObj["content-length"] = String(bodySize)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const lowercaseHeaders = {}
|
|
41
|
-
for (const [key, value] of Object.entries(headersObj)) {
|
|
42
|
-
lowercaseHeaders[key.toLowerCase()] = value
|
|
43
|
-
}
|
|
44
|
-
if (lowercaseHeaders.path && /^\//.test(lowercaseHeaders.path)) {
|
|
45
|
-
//const sp = lowercaseHeaders.path.split("/")
|
|
46
|
-
//lowercaseHeaders.path = sp.slice(sp.length - 1).join("/")
|
|
47
|
-
}
|
|
48
|
-
// Parse body-keys if present
|
|
49
|
-
const bodyKeys = headersObj["body-keys"]
|
|
50
|
-
? headersObj["body-keys"]
|
|
51
|
-
.replace(/"/g, "")
|
|
52
|
-
.split(",")
|
|
53
|
-
.map(k => k.trim())
|
|
54
|
-
: []
|
|
55
|
-
|
|
56
|
-
// Collect fields to sign from headers
|
|
57
|
-
const signingFields = Object.keys(lowercaseHeaders).filter(
|
|
58
|
-
key => key !== "body-keys" && key !== "path" && !bodyKeys.includes(key) // Also exclude fields that are in body-keys
|
|
59
|
-
)
|
|
60
|
-
// Always include @path in the signature
|
|
61
|
-
//if (!signingFields.includes("path")) signingFields.push("path")
|
|
62
|
-
if (_path) signingFields.push("path")
|
|
63
|
-
// Ensure we have at least one field to sign
|
|
64
|
-
if (signingFields.length === 0 && !body) {
|
|
65
|
-
lowercaseHeaders["content-length"] = "0"
|
|
66
|
-
signingFields.push("content-length")
|
|
67
|
-
}
|
|
59
|
+
const signedRequest = await toHttpSigner(signer)({
|
|
60
|
+
request: { url: _url, method, headers: lowercaseHeaders },
|
|
61
|
+
fields: signingFields,
|
|
62
|
+
})
|
|
68
63
|
|
|
69
|
-
|
|
70
|
-
request: {
|
|
71
|
-
url: _url,
|
|
72
|
-
method,
|
|
73
|
-
headers: lowercaseHeaders,
|
|
74
|
-
},
|
|
75
|
-
fields: signingFields,
|
|
76
|
-
})
|
|
77
|
-
const finalHeaders = {}
|
|
64
|
+
const finalHeaders = {}
|
|
78
65
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
66
|
+
for (const [key, value] of Object.entries(headersObj)) {
|
|
67
|
+
finalHeaders[key] = value
|
|
68
|
+
}
|
|
82
69
|
|
|
83
|
-
|
|
84
|
-
|
|
70
|
+
finalHeaders["signature"] = signedRequest.headers["signature"]
|
|
71
|
+
finalHeaders["signature-input"] = signedRequest.headers["signature-input"]
|
|
85
72
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
73
|
+
if (headersObj["body-keys"]) {
|
|
74
|
+
finalHeaders["body-keys"] = headersObj["body-keys"]
|
|
75
|
+
}
|
|
76
|
+
const result = { url: _url, method, headers: finalHeaders }
|
|
90
77
|
|
|
91
|
-
|
|
78
|
+
if (body) result.body = body
|
|
92
79
|
|
|
93
|
-
|
|
80
|
+
return result
|
|
81
|
+
}
|
|
82
|
+
export function signer(config) {
|
|
83
|
+
const { signer, url = "http://localhost:10001" } = config
|
|
84
|
+
if (!signer) throw new Error("Signer is required for mainnet mode")
|
|
85
|
+
return async (
|
|
86
|
+
fields,
|
|
87
|
+
{ encoded: _encoded = false, path: _path = false } = {}
|
|
88
|
+
) => {
|
|
89
|
+
const { path = "/relay/process", method = "POST", ...aoFields } = fields
|
|
90
|
+
const encoded = _encoded ? aoFields : await enc(aoFields)
|
|
91
|
+
return await _sign({ url, method, path, _path, encoded, signer })
|
|
94
92
|
}
|
|
95
93
|
}
|
|
96
|
-
|
|
97
|
-
// stack / simple-pay / patch / hyperbeam / hyperbeam-aos / scheduler / cron
|