Skip to content

Commit 070c5fb

Browse files
authored
Merge pull request #186 from hypercerts-org/fix/funding-receipt-field-types
fix: normalize funding receipt from/to/for field types
2 parents 73b0212 + 4408f61 commit 070c5fb

4 files changed

Lines changed: 79 additions & 31 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@hypercerts-org/lexicon": minor
3+
---
4+
5+
Normalize funding receipt fields: `from`/`to` as union of DID ref + strongRef, `from` optional, `for` changed to strongRef

SCHEMAS.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -263,19 +263,19 @@ Overall score for an evaluation on a numeric scale.
263263

264264
#### Properties
265265

266-
| Property | Type | Required | Description | Comments |
267-
| ---------------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
268-
| `from` | `ref` || DID of the sender who transferred the funds. This field is optional, and can be left undefined to represent anonymity. | |
269-
| `to` | `string` || The recipient of the funds. Can be identified by DID or a clear-text name. | maxLength: 2048 |
270-
| `amount` | `string` || Amount of funding received as a numeric string (e.g. '1000.50'). | maxLength: 50 |
271-
| `currency` | `string` || Currency of the payment (e.g. EUR, USD, ETH). | maxLength: 10 |
272-
| `paymentRail` | `string` || How the funds were transferred (e.g. bank_transfer, credit_card, onchain, cash, check, payment_processor). | maxLength: 50 |
273-
| `paymentNetwork` | `string` || Optional network within the payment rail (e.g. arbitrum, ethereum, sepa, visa, paypal). | maxLength: 50 |
274-
| `transactionId` | `string` || Identifier of the underlying payment transaction (e.g. bank reference, onchain transaction hash, or processor-specific ID). Use paymentNetwork to specify the network where applicable. | maxLength: 256 |
275-
| `for` | `string` || Optional reference to the activity, project, or organization this funding relates to. | |
276-
| `notes` | `string` || Optional notes or additional context for this funding receipt. | maxLength: 500 |
277-
| `occurredAt` | `string` || Timestamp when the payment occurred. | |
278-
| `createdAt` | `string` || Client-declared timestamp when this receipt record was created. | |
266+
| Property | Type | Required | Description | Comments |
267+
| ---------------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- |
268+
| `from` | `union` || The sender of the funds (either an account DID or a strong reference to a record). Optional — omit to represent anonymity. | |
269+
| `to` | `union` || The recipient of the funds (either an account DID or a strong reference to a record). | |
270+
| `amount` | `string` || Amount of funding received as a numeric string (e.g. '1000.50'). | maxLength: 50 |
271+
| `currency` | `string` || Currency of the payment (e.g. EUR, USD, ETH). | maxLength: 10 |
272+
| `paymentRail` | `string` || How the funds were transferred (e.g. bank_transfer, credit_card, onchain, cash, check, payment_processor). | maxLength: 50 |
273+
| `paymentNetwork` | `string` || Optional network within the payment rail (e.g. arbitrum, ethereum, sepa, visa, paypal). | maxLength: 50 |
274+
| `transactionId` | `string` || Identifier of the underlying payment transaction (e.g. bank reference, onchain transaction hash, or processor-specific ID). Use paymentNetwork to specify the network where applicable. | maxLength: 256 |
275+
| `for` | `ref` || Optional strong reference to the activity, project, or organization this funding relates to. | |
276+
| `notes` | `string` || Optional notes or additional context for this funding receipt. | maxLength: 500 |
277+
| `occurredAt` | `string` || Timestamp when the payment occurred. | |
278+
| `createdAt` | `string` || Client-declared timestamp when this receipt record was created. | |
279279

280280
---
281281

lexicons/org/hypercerts/funding/receipt.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@
1111
"required": ["to", "amount", "currency", "createdAt"],
1212
"properties": {
1313
"from": {
14-
"type": "ref",
15-
"ref": "app.certified.defs#did",
16-
"description": "DID of the sender who transferred the funds. This field is optional, and can be left undefined to represent anonymity."
14+
"type": "union",
15+
"description": "The sender of the funds (either an account DID or a strong reference to a record). Optional — omit to represent anonymity.",
16+
"refs": ["app.certified.defs#did", "com.atproto.repo.strongRef"]
1717
},
1818
"to": {
19-
"type": "string",
20-
"description": "The recipient of the funds. Can be identified by DID or a clear-text name.",
21-
"maxLength": 2048
19+
"type": "union",
20+
"description": "The recipient of the funds (either an account DID or a strong reference to a record).",
21+
"refs": ["app.certified.defs#did", "com.atproto.repo.strongRef"]
2222
},
2323
"amount": {
2424
"type": "string",
@@ -46,9 +46,9 @@
4646
"maxLength": 256
4747
},
4848
"for": {
49-
"type": "string",
50-
"format": "at-uri",
51-
"description": "Optional reference to the activity, project, or organization this funding relates to."
49+
"type": "ref",
50+
"ref": "com.atproto.repo.strongRef",
51+
"description": "Optional strong reference to the activity, project, or organization this funding relates to."
5252
},
5353
"notes": {
5454
"type": "string",

tests/validate-funding-receipt.test.ts

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { validate, ids } from "../generated/lexicons.js";
33
import * as FundingReceipt from "../generated/types/org/hypercerts/funding/receipt.js";
44

55
const validBase = {
6-
to: "Alice",
6+
to: { $type: "app.certified.defs#did", did: "did:plc:recipient123" },
77
amount: "1000.00",
88
currency: "USD",
99
createdAt: "2024-01-01T00:00:00Z",
@@ -17,7 +17,7 @@ describe("org.hypercerts.funding.receipt", () => {
1717
});
1818
expect(result.success).toBe(true);
1919
if (result.success) {
20-
expect(result.value.to).toBe("Alice");
20+
expect(result.value.to).toMatchObject({ did: "did:plc:recipient123" });
2121
expect(result.value.amount).toBe("1000.00");
2222
expect(result.value.currency).toBe("USD");
2323
}
@@ -34,27 +34,58 @@ describe("org.hypercerts.funding.receipt", () => {
3434
}
3535
});
3636

37-
it("should accept a valid record with the optional 'from' field present", () => {
37+
it("should accept a valid record with 'from' as a DID", () => {
3838
const result = FundingReceipt.validateMain({
3939
$type: ids.OrgHypercertsFundingReceipt,
4040
...validBase,
41-
from: { did: "did:plc:abc123" },
41+
from: { $type: "app.certified.defs#did", did: "did:plc:abc123" },
4242
});
4343
expect(result.success).toBe(true);
4444
if (result.success) {
4545
expect(result.value.from).toMatchObject({ did: "did:plc:abc123" });
4646
}
4747
});
4848

49+
it("should accept 'to' as a strongRef", () => {
50+
const result = FundingReceipt.validateMain({
51+
$type: ids.OrgHypercertsFundingReceipt,
52+
to: {
53+
$type: "com.atproto.repo.strongRef",
54+
uri: "at://did:plc:recipient123/org.hypercerts.contributor.information/tid456",
55+
cid: "bafyreie5737gdxlw5i64vngml6xvqeatqy3a4erphoqtso54z2eooh4zae",
56+
},
57+
amount: "1000.00",
58+
currency: "USD",
59+
createdAt: "2024-01-01T00:00:00Z",
60+
});
61+
expect(result.success).toBe(true);
62+
});
63+
64+
it("should accept 'from' as a strongRef", () => {
65+
const result = FundingReceipt.validateMain({
66+
$type: ids.OrgHypercertsFundingReceipt,
67+
...validBase,
68+
from: {
69+
$type: "com.atproto.repo.strongRef",
70+
uri: "at://did:plc:abc123/org.hypercerts.contributor.information/tid789",
71+
cid: "bafyreie5737gdxlw5i64vngml6xvqeatqy3a4erphoqtso54z2eooh4zae",
72+
},
73+
});
74+
expect(result.success).toBe(true);
75+
});
76+
4977
it("should accept a valid record with all optional fields present", () => {
5078
const result = FundingReceipt.validateMain({
5179
$type: ids.OrgHypercertsFundingReceipt,
5280
...validBase,
53-
from: { did: "did:plc:abc123" },
81+
from: { $type: "app.certified.defs#did", did: "did:plc:abc123" },
5482
paymentRail: "onchain",
5583
paymentNetwork: "ethereum",
5684
transactionId: "0xabc123",
57-
for: "at://did:plc:abc123/org.hypercerts.claim.activity/tid123",
85+
for: {
86+
uri: "at://did:plc:abc123/org.hypercerts.claim.activity/tid123",
87+
cid: "bafyreie5737gdxlw5i64vngml6xvqeatqy3a4erphoqtso54z2eooh4zae",
88+
},
5889
notes: "Quarterly donation",
5990
occurredAt: "2024-01-01T00:00:00Z",
6091
});
@@ -73,7 +104,11 @@ describe("org.hypercerts.funding.receipt", () => {
73104

74105
it("should reject a record missing the required 'amount' field", () => {
75106
const result = validate(
76-
{ to: "Alice", currency: "EUR", createdAt: "2024-01-01T00:00:00Z" },
107+
{
108+
to: { $type: "app.certified.defs#did", did: "did:plc:recipient123" },
109+
currency: "EUR",
110+
createdAt: "2024-01-01T00:00:00Z",
111+
},
77112
ids.OrgHypercertsFundingReceipt,
78113
"main",
79114
false,
@@ -83,7 +118,11 @@ describe("org.hypercerts.funding.receipt", () => {
83118

84119
it("should reject a record missing the required 'currency' field", () => {
85120
const result = validate(
86-
{ to: "Alice", amount: "500", createdAt: "2024-01-01T00:00:00Z" },
121+
{
122+
to: { $type: "app.certified.defs#did", did: "did:plc:recipient123" },
123+
amount: "500",
124+
createdAt: "2024-01-01T00:00:00Z",
125+
},
87126
ids.OrgHypercertsFundingReceipt,
88127
"main",
89128
false,
@@ -93,7 +132,11 @@ describe("org.hypercerts.funding.receipt", () => {
93132

94133
it("should reject a record missing the required 'createdAt' field", () => {
95134
const result = validate(
96-
{ to: "Alice", amount: "500", currency: "USD" },
135+
{
136+
to: { $type: "app.certified.defs#did", did: "did:plc:recipient123" },
137+
amount: "500",
138+
currency: "USD",
139+
},
97140
ids.OrgHypercertsFundingReceipt,
98141
"main",
99142
false,

0 commit comments

Comments
 (0)