damus-io / damus

iOS nostr client
GNU General Public License v3.0
2k stars 289 forks source link

Bug: Damus not displaying zaps from Alby wallet #2363

Closed dmnyc closed 2 months ago

dmnyc commented 3 months ago

I am no longer seeing any zaps sent to my Alby Lightning address.

Is this a Damus issue or an Alby one?

I'm asking because I see all zap counts correctly in Nostur, Amethyst and other clients.

image image image image

jb55 commented 3 months ago

I just need the id of the zap and I can debug. most common issue is that the zapper pubkey is not set correctly. if other clients are accepting these as valid then they are succeptible to fake zap attacks.

dmnyc commented 3 months ago

How do I find the zap ID? I can provide this note as an example:

note1scd3msunu7q6nn0rzan9qehs8vu8xdnqas75r3rg220y994rpf7q2xw70a

https://nostr.band/note1scd3msunu7q6nn0rzan9qehs8vu8xdnqas75r3rg220y994rpf7q2xw70a?overview=zaps-received

Screenshot 2024-08-05 at 2 25 10β€―PM

dmnyc commented 3 months ago

@tyiu found it for me:

https://njump.me/nevent1qqsghvmvwlc7dflvuldjeelcwq7x8s4r05alv2ac6m4rgenk7083asqprpmhxue69uhhyetvv9ujumn0wdmksetjv5hxxmmdqyt8wumn8ghj7un9d3shjtnswf5k6ctv9ehx2aqzypulqrfltgv7eqrp3872kq7phe8ls8gcae8k20ygltzplcp4wr6ryeefrln

rolznz commented 3 months ago

This also happens to me. It's not a particular zap, it's all zaps https://github.com/damus-io/damus/issues/2356

rolznz commented 2 months ago

Any update on this? it's not just Alby Wallet. Users with LNbits too. Viewing zaps on Nostrudel and Primal have no issue. On Damus, the zaps don't show at all.

Would some sort of bounty help this to be prioritized? I would be happy to pay 100K sats for a proper fix

alltheseas commented 2 months ago

https://damus.io/note14lh7twqhmvs6rhqvsjujmyceuzzt7rsggc2jz4cccvcn24qetznsxgcp4d

Additional report

jb55 commented 2 months ago

Any update on this? it's not just Alby Wallet. Users with LNbits too. Viewing zaps on Nostrudel and Primal have no issue. On Damus, the zaps don't show at all.

Would some sort of bounty help this to be prioritized? I would be happy to pay 100K sats for a proper fix

I unfortunately don't have a lot a time to debug every zapper implementation, hopefully someone who uses alby hub can help fix this by debugging inside damus and see why its getting marked as invalid.

rolznz commented 2 months ago

@jb55 this isn't a zapper implementation issue, it's a zap validation issue. I queried all the zap events on my post.

Damus only shows 1 zap (The Blockstream one).

I queried all the zap receipts from the damus relay for this event. On the Damus relay there are 5 zaps. I checked them all against the NIP-57 Appendix F: Validating Zap Requests and all 5 zaps pass.

I've attached the events I got and the code, and the result. All the events I believe are valid, Damus is doing some extra filtering which is outside of that appendix.

import { Invoice } from "@getalby/lightning-tools";

const zaps = [
  {
    content: "🐝 Self-custodial zap straight from my Alby Hub 🐝",
    created_at: 1724753768,
    id: "326978e1885a2f9db30353e5d343314499db7365db2220b16ac9cf99f71de4a7",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "0ff4e67977a4a5463eee56976e80f23e3cc1de652f5e19a3948d7342269a843ae82d3d3d037ada39a497a1f7f38f778c373852d2fee2c272a49ead7f6f227232",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "dbe0605a9c73172bad7523a327b236d55ea4b634e80e78a9013db791f8fd5b2c"],
      [
        "bolt11",
        "lnbc10u1pnvmfmzdzh7z0ep8fq2djkce3dvd6hxar0v35kzmpq0fshqgrnw3exz6t8dp6zqenjdakjqmteypqkccneypy82c3q7z0ep8gnp4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp582spvlvy8eqtygnm5lkq6hn7wny32y30adzsqscy9ac7wpgrtulssp5ef57gq4key5x36mq0galy2flwmgvnd2stxlly3955q08dl5fp32s9qyysgqcqpcxqyz5vq9ceug5wt8lyqmfxcyqu4awmvkfxypw6mngew5zehk96aa9mtjk6yfr92u2jmd32h0xhx9ays4fnkt0uwfas47c7nrjrhymcpqymsqwgq0lz7ry",
      ],
      [
        "preimage",
        "be4450bea8efbbe6fe2052365f827e8d74a1f8dc296769362346ebcf10062c04",
      ],
      [
        "description",
        '{"kind":9734,"created_at":1724753762,"content":"🐝 Self-custodial zap straight from my Alby Hub 🐝","tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["amount","1000000"],["relays","wss://nostr.kosmos.org","wss://relay.damus.io","wss://filter.nostr.wine","wss://nostr.wine","wss://relay.primal.net"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"]],"pubkey":"dbe0605a9c73172bad7523a327b236d55ea4b634e80e78a9013db791f8fd5b2c","id":"bef0096cb84c2b933785f8d5d62f3e45eab9dffceff72bacf3174f6d7ab22f13","sig":"83ab6ae263645872880e08a21730064c7ecbcc2bd6f2ca50f4b4ad165507167f9275dd0e77220186c3c2f39f0917d36952cf2e6f52ba1cd9407e4c584144b1b0"}',
      ],
    ],
  },
  {
    content: "🐝 Self-custodial zap straight from my Alby Hub 🐝",
    created_at: 1724753679,
    id: "0cf681e27142e967770adaf27c98852128e788803e5d60725b974a48b0d3f6a8",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "d17074bb41d76e6e05c12f1eefae863deb05417c13d45aeb55a08bb83912a0e87b6a963ef7d7479e2873fab3baa41a6d1d55ee8fc6bea61f2fb6b31281f7cac6",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "dbe0605a9c73172bad7523a327b236d55ea4b634e80e78a9013db791f8fd5b2c"],
      [
        "bolt11",
        "lnbc10u1pnvmfcfdzh7z0ep8fq2djkce3dvd6hxar0v35kzmpq0fshqgrnw3exz6t8dp6zqenjdakjqmteypqkccneypy82c3q7z0ep8gnp4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp59xvx3drr4qe9u0wwgdkk4a4qk9d7qrg9hdp220r0p422hcjgxesqsp53xmhh60vkayp2arj576x4xrjcr9cmm45pn4fvnlm2dvwkz4qpsrq9qyysgqcqpcxqyz5vqn9m0x0s78tuvkwgjgey0dpyznn7vd5yjzqn3vckzwzahuk6qem089hpeljja87549rdqgxd39pg5h09strxjlxczt2w4drlwdk28cgspvh7kks",
      ],
      [
        "preimage",
        "7a17efa10aa201cbff8794fa2ab8994145d59b80c40c804796244419abea3a59",
      ],
      [
        "description",
        '{"kind":9734,"created_at":1724753673,"content":"🐝 Self-custodial zap straight from my Alby Hub 🐝","tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["amount","1000000"],["relays","wss://nostr.kosmos.org","wss://relay.damus.io","wss://filter.nostr.wine","wss://nostr.wine","wss://relay.primal.net"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"]],"pubkey":"dbe0605a9c73172bad7523a327b236d55ea4b634e80e78a9013db791f8fd5b2c","id":"339f6955524d3d91ce6dbfb092c93c86bedbf75521413e3b384c85da319093bc","sig":"2c45dd89c480cff16fc50b7ad62faeecc2b0e6266a64b764ca9ce31cfac017921b0e2de146da6d952530959a0967e7c33495f34dcc076e3e9f5ff185bfab6eb0"}',
      ],
    ],
  },
  {
    content: "Let's go πŸš€",
    created_at: 1724753566,
    id: "ec9aeae0da1aada7a7524aa832e4f3fc740d1e6fe527f23183acb98427460f10",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "b8ca51829b3d57015f9b9d5366ca07732b83b8d522e2090b62352befa826463b9c9fb54807e8bf20e9545f9ff3f4479496aefcae9e5fad8eb27668556ad4c350",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "90d9080b825ff98e9bb60f5735ff7ee5c5db6267ab93a3ec7b1d5d30374bba8a"],
      [
        "bolt11",
        "lnbc4200n1pnvmf5mdq4f3jhgfmnypnk7g8sn7dgqnp4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp54gz8wngaaems7ptawjk0qgyaqg369lu3k5adrq5mmc6guuejfksssp5jmlg9340q5fhckzxq7j84q60mtfexg9dhzrqtml959ducejt2kss9qyysgqcqpcxqyz5vqpr5uw3y8ngjkgdydemj62fsxuw3y3huj9fw07yg5d8zgste0pmjy4vsunvk7tfm8y7kxgweyjwye5vvcudl6qf05rp34pcur92v6qmgpv6j7ag",
      ],
      [
        "preimage",
        "2ac90e2e376eefc16cff1f179d4169ebc885b0ad119fb0eb65515a6914288ab9",
      ],
      [
        "description",
        `{"id":"77fc11164d2af1e94d1fd493927f305523e99faaa6607d66abdfcdb1472a3d9f","pubkey":"90d9080b825ff98e9bb60f5735ff7ee5c5db6267ab93a3ec7b1d5d30374bba8a","created_at":1724753540,"kind":9734,"tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],["amount","420000"],["relays","wss://relay.nostr.bg","wss://relay.primal.net","wss://atlas.nostr.land","wss://relay.snort.social","wss://relay.noswhere.com","wss://puravida.nostr.land","wss://nostr.land","wss://nostr.wine","wss://nostr.oxtr.dev","wss://relay.nostr.band","wss://eden.nostr.land","wss://nos.lol","wss://nostr.mutinywallet.com","wss://filter.nostr.wine/npub1jrvsszuztlucaxakpatntlm7uhzakcn84wf68mrmr4wnqd6th29q45zaq8?broadcast=true","wss://lightningrelay.com","ws://znwu44n74shn2byicqfmmzcs4aed4gzplahtixkzktejrjq2ccaw4oid.onion","wss://relay.damus.io"]],"content":"Let's go πŸš€","sig":"3fc0503f0a8c8829d1d3bdf00233c59a6cb4875683f4dfc2170cd9c6a29141cd1183788585bb5f826b54f19f4069ea0eddf5cfe19580044cfe2bacf18b5a4843"}`,
      ],
    ],
  },
  {
    content: "Blockstream",
    created_at: 1724736543,
    id: "0db388e1cebfb64e95cb42a3d960a5a71832afe0e62b2cff8ad52c08a2601281",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "66a18b6bd17cfb4666329583d5c47b04bcebdfe4e9085a2807a2c0c2f0348d4f578beba0750f746d89b31aeaab1371af84486c8d75ad25887b399b56b00e1f57",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "922945779f93fd0b3759f1157e3d9fa20f3fd24c4b8f2bcf520cacf649af776d"],
      [
        "bolt11",
        "lnbc210n1pnv6cwadqjgfkx7cmtwd68yetpd5np4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp5rjev3zax7dfxx04aw7pxzgy6kh2ztrwcp85gpgsl8sfxv6xvahpssp5638hzqk36nl2x8qn7caehvqdpzjklvc3ced8w09vgyd0pa38ue9q9qyysgqcqpcxqyz5vqul26t4ngs64jyywqtmrlmg7wpl0k6hnjg4e02z6gwrkwk9cshsq5jmcau7x00xkjy9m8jpt8rwvgp8ap2ymndhrgp9qw9mrytza4vxqqn4tm28",
      ],
      [
        "preimage",
        "4310d13eebde38fdb0bc90286a46b7454a0845a3346aebe5376b9de87261e46c",
      ],
      [
        "description",
        '{"id":"834cd17e414c27b3238db9b5a5a90231eabff69d3f8742d98c53349f2344c6c9","sig":"875f7e25f270395262557cddd8137b84e54da895272407d25b75055d300da31eee991306d43ea26b211e724cf06c8bcd4d381b15fadd64c15991e559ae0ac49d","kind":9734,"tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["amount","21000"],["relays","wss://cache2.primal.net/v1","wss://welcome.nostr.wine","wss://nostr.mutinywallet.com","wss://nostr.wine","wss://relay.nostr.bg","wss://purplepag.es","wss://nos.lol","wss://nostr.fmt.wiz.biz","wss://nostr.oxtr.dev","wss://offchain.pub","wss://relay.primal.net","wss://relay.damus.io","wss://eden.nostr.land","wss://n.ok0.org"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"]],"pubkey":"922945779f93fd0b3759f1157e3d9fa20f3fd24c4b8f2bcf520cacf649af776d","content":"Blockstream","created_at":1724735924}',
      ],
    ],
  },
  {
    content: "⚑Non-custodial zap from my Alby Hub",
    created_at: 1724685047,
    id: "4c75ab1e7098ccb7aeb8ff7d420236d357e58ccfb79fbe101704cb364987b68a",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "79c9d2c7a1eb56caf32965e4d02eb2bb1fa674eb038ea62ace86c0b30692a254ae43ba6c367202df817494ca58874d5b59c1cea07ce992942b29f0feefbe3abd",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "0521db9531096dff700dcf410b01db47ab6598de7e5ef2c5a2bd7e1160315bf6"],
      [
        "bolt11",
        "lnbc10u1pnvexh3dpuu2d2znn0dckkxatnw3hkg6tpdss85ctsypn8ymmdypkhjgzpd338jgzgw43qnp4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp5vlcll00zpphh32w8ut5jpp5a2fmqh8sz7nu2h7v07r0u5lswg5lssp5xvaqefzlckzmv0w89lr0k0yvr5xd2ng52a5rcdarfm4f0a0wgpuq9qyysgqcqpcxqyz5vqeps39sex52sfmtu9gnm5dapk5lgld4pp96ur5a4am940q25wzdsrrj523xya0ruxa5lr963g0296r6mdfy24v653evcpxyr0mmhgwmsqxvrhfd",
      ],
      [
        "preimage",
        "ad047c02fe5f059c80877d794be88e47c644ebedfdfe663b289c9316db495f2d",
      ],
      [
        "description",
        '{"kind":9734,"created_at":1724685038,"content":"⚑Non-custodial zap from my Alby Hub","tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["relays","wss://purplepag.es/","wss://relay.getalby.com/v1","wss://nostr.mom/","wss://nostr.oxtr.dev/","wss://nos.lol/","wss://nostr.wine/","wss://relay.damus.io/","wss://relay.notoshi.win/","wss://eden.nostr.land/"],["amount","1000000"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"]],"pubkey":"0521db9531096dff700dcf410b01db47ab6598de7e5ef2c5a2bd7e1160315bf6","id":"57d8612007521c0b532b91af2498095a251e63f425187e6c95700fd0a6bab7d4","sig":"798d735118bcd14228a12b6d52423ff25bb4ed8cd5dacf2f5971ef573fdc3fc05fc793185e69682cca243d64f147a4498968a0bc288ae83e75c03e99f936a603"}',
      ],
    ],
  },
];

// https://github.com/nostr-protocol/nips/blob/master/57.md#appendix-f-validating-zap-receipts

// https://getalby.com/.well-known/nostr.json?name=rolznz
const nostrPubkey =
  "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e";

// My pubkey in Damus is npub1zk6u7mxlflguqteghn8q7xtu47hyerruv6379c36l8lxzzr4x90q0gl6ef
// decoded = 15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e (same as my nostrPubkey above)

for (const zap of zaps) {
  // 1. The zap receipt event's pubkey MUST be the same as the recipient's lnurl provider's nostrPubkey (retrieved in step 1 of the protocol flow).
  const pTag = zap.tags.find((tag) => tag[0] === "p");
  if (pTag?.[1] !== nostrPubkey) {
    console.error("Incorrect p tag for zap", zap.id);
    continue;
  }

  // The invoiceAmount contained in the bolt11 tag of the zap receipt MUST equal the amount tag of the zap request (if present).
  const bolt11 = zap.tags.find((tag) => tag[0] === "bolt11")?.[1];
  if (!bolt11) {
    console.error("No bolt11 tag for zap", zap.id);
    continue;
  }

  const zapRequestTagValue = zap.tags.find(
    (tag) => tag[0] === "description"
  )?.[1];
  if (!zapRequestTagValue) {
    console.error("No description tag for zap", zap.id);
    continue;
  }
  const zapRequest = JSON.parse(zapRequestTagValue);
  const zapRequestAmountTag = (zapRequest.tags as string[][]).find(
    (tag) => tag[0] === "amount"
  )?.[1];

  if (zapRequestAmountTag) {
    try {
      const invoice = new Invoice({
        pr: bolt11,
      });
      if (+zapRequestAmountTag != invoice.satoshi * 1000) {
        console.error(
          "Zap amount doesn't match invoice",
          +zapRequestAmountTag,
          invoice.satoshi,
          zap.id
        );
        continue;
      }
    } catch (error) {
      console.error("Failed to parse bolt11 for zap", zap.id, error);
      continue;
    }
  } else {
    console.log("No amount tag in zap request for zap", zap.id);
  }

  // The lnurl tag of the zap request (if present) SHOULD equal the recipient's lnurl.
  // None of the zaps have lnurl tags, so skipping.

  console.log("Zap OK", zap.id);
}

Result:

$ ts-node zaps.ts
Zap OK 326978e1885a2f9db30353e5d343314499db7365db2220b16ac9cf99f71de4a7
Zap OK 0cf681e27142e967770adaf27c98852128e788803e5d60725b974a48b0d3f6a8
Zap OK ec9aeae0da1aada7a7524aa832e4f3fc740d1e6fe527f23183acb98427460f10
Zap OK 0db388e1cebfb64e95cb42a3d960a5a71832afe0e62b2cff8ad52c08a2601281
Zap OK 4c75ab1e7098ccb7aeb8ff7d420236d357e58ccfb79fbe101704cb364987b68a
Done in 1.48s.

I don't have a mac so this is very difficult for me to debug this further. But this is obviously a Damus issue, not a zapper implementation issue.

rolznz commented 2 months ago

Compare this to what you see on Nostrudel (14 zaps) Primal (14 zaps) Snort (14 zaps)

Damus: 1 zap.

jb55 commented 2 months ago

the only thing I can think of is maybe its failing to decode the bolt11 properly, ~since when I took a look the validation looked ok.~

I have time this morning to at least write a test so maybe that will uncover the issue.

jb55 commented 2 months ago

its very clear in these examples that the zapper nostrPubkey does not match the pubkey of the zap note... that is what is wrong

jb55 commented 2 months ago

the fact that other clients are not catching this means that you can fake zaps on any of those clients. that's insanely bad.

rolznz commented 2 months ago

Which pubkey is this? Alby runs one zapper for all accounts. So there is no way the pubkey can match. The "p" tag matches.

jb55 commented 2 months ago

the pubkey of the zap note 9735 has to match the nostrPubkey in the lnurl endpoint. this is how zaps are spec'd

// https://getalby.com/.well-known/nostr.json?name=rolznz
const nostrPubkey =
  "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e";

the 9735 pubkey should be this, but it looks like they are 79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432 in your example

jb55 commented 2 months ago

the nostrPubkey is the pubkey of the lightning node that makes the zaps, not the user's pubkey

jb55 commented 2 months ago

do you have an example albyhub lnurl nostrPubkey, I just realized maybe I was just confused by the variable name...

rolznz commented 2 months ago

Sorry, I did look at the wrong endpoint. https://getalby.com/.well-known/lnurlp/rolznz

rolznz commented 2 months ago

Updated code:

import { Invoice } from "@getalby/lightning-tools";

const zaps = [
  {
    content: "🐝 Self-custodial zap straight from my Alby Hub 🐝",
    created_at: 1724753768,
    id: "326978e1885a2f9db30353e5d343314499db7365db2220b16ac9cf99f71de4a7",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "0ff4e67977a4a5463eee56976e80f23e3cc1de652f5e19a3948d7342269a843ae82d3d3d037ada39a497a1f7f38f778c373852d2fee2c272a49ead7f6f227232",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "dbe0605a9c73172bad7523a327b236d55ea4b634e80e78a9013db791f8fd5b2c"],
      [
        "bolt11",
        "lnbc10u1pnvmfmzdzh7z0ep8fq2djkce3dvd6hxar0v35kzmpq0fshqgrnw3exz6t8dp6zqenjdakjqmteypqkccneypy82c3q7z0ep8gnp4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp582spvlvy8eqtygnm5lkq6hn7wny32y30adzsqscy9ac7wpgrtulssp5ef57gq4key5x36mq0galy2flwmgvnd2stxlly3955q08dl5fp32s9qyysgqcqpcxqyz5vq9ceug5wt8lyqmfxcyqu4awmvkfxypw6mngew5zehk96aa9mtjk6yfr92u2jmd32h0xhx9ays4fnkt0uwfas47c7nrjrhymcpqymsqwgq0lz7ry",
      ],
      [
        "preimage",
        "be4450bea8efbbe6fe2052365f827e8d74a1f8dc296769362346ebcf10062c04",
      ],
      [
        "description",
        '{"kind":9734,"created_at":1724753762,"content":"🐝 Self-custodial zap straight from my Alby Hub 🐝","tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["amount","1000000"],["relays","wss://nostr.kosmos.org","wss://relay.damus.io","wss://filter.nostr.wine","wss://nostr.wine","wss://relay.primal.net"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"]],"pubkey":"dbe0605a9c73172bad7523a327b236d55ea4b634e80e78a9013db791f8fd5b2c","id":"bef0096cb84c2b933785f8d5d62f3e45eab9dffceff72bacf3174f6d7ab22f13","sig":"83ab6ae263645872880e08a21730064c7ecbcc2bd6f2ca50f4b4ad165507167f9275dd0e77220186c3c2f39f0917d36952cf2e6f52ba1cd9407e4c584144b1b0"}',
      ],
    ],
  },
  {
    content: "🐝 Self-custodial zap straight from my Alby Hub 🐝",
    created_at: 1724753679,
    id: "0cf681e27142e967770adaf27c98852128e788803e5d60725b974a48b0d3f6a8",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "d17074bb41d76e6e05c12f1eefae863deb05417c13d45aeb55a08bb83912a0e87b6a963ef7d7479e2873fab3baa41a6d1d55ee8fc6bea61f2fb6b31281f7cac6",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "dbe0605a9c73172bad7523a327b236d55ea4b634e80e78a9013db791f8fd5b2c"],
      [
        "bolt11",
        "lnbc10u1pnvmfcfdzh7z0ep8fq2djkce3dvd6hxar0v35kzmpq0fshqgrnw3exz6t8dp6zqenjdakjqmteypqkccneypy82c3q7z0ep8gnp4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp59xvx3drr4qe9u0wwgdkk4a4qk9d7qrg9hdp220r0p422hcjgxesqsp53xmhh60vkayp2arj576x4xrjcr9cmm45pn4fvnlm2dvwkz4qpsrq9qyysgqcqpcxqyz5vqn9m0x0s78tuvkwgjgey0dpyznn7vd5yjzqn3vckzwzahuk6qem089hpeljja87549rdqgxd39pg5h09strxjlxczt2w4drlwdk28cgspvh7kks",
      ],
      [
        "preimage",
        "7a17efa10aa201cbff8794fa2ab8994145d59b80c40c804796244419abea3a59",
      ],
      [
        "description",
        '{"kind":9734,"created_at":1724753673,"content":"🐝 Self-custodial zap straight from my Alby Hub 🐝","tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["amount","1000000"],["relays","wss://nostr.kosmos.org","wss://relay.damus.io","wss://filter.nostr.wine","wss://nostr.wine","wss://relay.primal.net"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"]],"pubkey":"dbe0605a9c73172bad7523a327b236d55ea4b634e80e78a9013db791f8fd5b2c","id":"339f6955524d3d91ce6dbfb092c93c86bedbf75521413e3b384c85da319093bc","sig":"2c45dd89c480cff16fc50b7ad62faeecc2b0e6266a64b764ca9ce31cfac017921b0e2de146da6d952530959a0967e7c33495f34dcc076e3e9f5ff185bfab6eb0"}',
      ],
    ],
  },
  {
    content: "Let's go πŸš€",
    created_at: 1724753566,
    id: "ec9aeae0da1aada7a7524aa832e4f3fc740d1e6fe527f23183acb98427460f10",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "b8ca51829b3d57015f9b9d5366ca07732b83b8d522e2090b62352befa826463b9c9fb54807e8bf20e9545f9ff3f4479496aefcae9e5fad8eb27668556ad4c350",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "90d9080b825ff98e9bb60f5735ff7ee5c5db6267ab93a3ec7b1d5d30374bba8a"],
      [
        "bolt11",
        "lnbc4200n1pnvmf5mdq4f3jhgfmnypnk7g8sn7dgqnp4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp54gz8wngaaems7ptawjk0qgyaqg369lu3k5adrq5mmc6guuejfksssp5jmlg9340q5fhckzxq7j84q60mtfexg9dhzrqtml959ducejt2kss9qyysgqcqpcxqyz5vqpr5uw3y8ngjkgdydemj62fsxuw3y3huj9fw07yg5d8zgste0pmjy4vsunvk7tfm8y7kxgweyjwye5vvcudl6qf05rp34pcur92v6qmgpv6j7ag",
      ],
      [
        "preimage",
        "2ac90e2e376eefc16cff1f179d4169ebc885b0ad119fb0eb65515a6914288ab9",
      ],
      [
        "description",
        `{"id":"77fc11164d2af1e94d1fd493927f305523e99faaa6607d66abdfcdb1472a3d9f","pubkey":"90d9080b825ff98e9bb60f5735ff7ee5c5db6267ab93a3ec7b1d5d30374bba8a","created_at":1724753540,"kind":9734,"tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],["amount","420000"],["relays","wss://relay.nostr.bg","wss://relay.primal.net","wss://atlas.nostr.land","wss://relay.snort.social","wss://relay.noswhere.com","wss://puravida.nostr.land","wss://nostr.land","wss://nostr.wine","wss://nostr.oxtr.dev","wss://relay.nostr.band","wss://eden.nostr.land","wss://nos.lol","wss://nostr.mutinywallet.com","wss://filter.nostr.wine/npub1jrvsszuztlucaxakpatntlm7uhzakcn84wf68mrmr4wnqd6th29q45zaq8?broadcast=true","wss://lightningrelay.com","ws://znwu44n74shn2byicqfmmzcs4aed4gzplahtixkzktejrjq2ccaw4oid.onion","wss://relay.damus.io"]],"content":"Let's go πŸš€","sig":"3fc0503f0a8c8829d1d3bdf00233c59a6cb4875683f4dfc2170cd9c6a29141cd1183788585bb5f826b54f19f4069ea0eddf5cfe19580044cfe2bacf18b5a4843"}`,
      ],
    ],
  },
  {
    content: "Blockstream",
    created_at: 1724736543,
    id: "0db388e1cebfb64e95cb42a3d960a5a71832afe0e62b2cff8ad52c08a2601281",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "66a18b6bd17cfb4666329583d5c47b04bcebdfe4e9085a2807a2c0c2f0348d4f578beba0750f746d89b31aeaab1371af84486c8d75ad25887b399b56b00e1f57",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "922945779f93fd0b3759f1157e3d9fa20f3fd24c4b8f2bcf520cacf649af776d"],
      [
        "bolt11",
        "lnbc210n1pnv6cwadqjgfkx7cmtwd68yetpd5np4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp5rjev3zax7dfxx04aw7pxzgy6kh2ztrwcp85gpgsl8sfxv6xvahpssp5638hzqk36nl2x8qn7caehvqdpzjklvc3ced8w09vgyd0pa38ue9q9qyysgqcqpcxqyz5vqul26t4ngs64jyywqtmrlmg7wpl0k6hnjg4e02z6gwrkwk9cshsq5jmcau7x00xkjy9m8jpt8rwvgp8ap2ymndhrgp9qw9mrytza4vxqqn4tm28",
      ],
      [
        "preimage",
        "4310d13eebde38fdb0bc90286a46b7454a0845a3346aebe5376b9de87261e46c",
      ],
      [
        "description",
        '{"id":"834cd17e414c27b3238db9b5a5a90231eabff69d3f8742d98c53349f2344c6c9","sig":"875f7e25f270395262557cddd8137b84e54da895272407d25b75055d300da31eee991306d43ea26b211e724cf06c8bcd4d381b15fadd64c15991e559ae0ac49d","kind":9734,"tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["amount","21000"],["relays","wss://cache2.primal.net/v1","wss://welcome.nostr.wine","wss://nostr.mutinywallet.com","wss://nostr.wine","wss://relay.nostr.bg","wss://purplepag.es","wss://nos.lol","wss://nostr.fmt.wiz.biz","wss://nostr.oxtr.dev","wss://offchain.pub","wss://relay.primal.net","wss://relay.damus.io","wss://eden.nostr.land","wss://n.ok0.org"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"]],"pubkey":"922945779f93fd0b3759f1157e3d9fa20f3fd24c4b8f2bcf520cacf649af776d","content":"Blockstream","created_at":1724735924}',
      ],
    ],
  },
  {
    content: "⚑Non-custodial zap from my Alby Hub",
    created_at: 1724685047,
    id: "4c75ab1e7098ccb7aeb8ff7d420236d357e58ccfb79fbe101704cb364987b68a",
    kind: 9735,
    pubkey: "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432",
    sig: "79c9d2c7a1eb56caf32965e4d02eb2bb1fa674eb038ea62ace86c0b30692a254ae43ba6c367202df817494ca58874d5b59c1cea07ce992942b29f0feefbe3abd",
    tags: [
      ["p", "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],
      ["e", "bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"],
      ["P", "0521db9531096dff700dcf410b01db47ab6598de7e5ef2c5a2bd7e1160315bf6"],
      [
        "bolt11",
        "lnbc10u1pnvexh3dpuu2d2znn0dckkxatnw3hkg6tpdss85ctsypn8ymmdypkhjgzpd338jgzgw43qnp4q228a2ztxkwzaypvzrsh823qngmv97f2v9puwvtsadetypmutyscwpp5vlcll00zpphh32w8ut5jpp5a2fmqh8sz7nu2h7v07r0u5lswg5lssp5xvaqefzlckzmv0w89lr0k0yvr5xd2ng52a5rcdarfm4f0a0wgpuq9qyysgqcqpcxqyz5vqeps39sex52sfmtu9gnm5dapk5lgld4pp96ur5a4am940q25wzdsrrj523xya0ruxa5lr963g0296r6mdfy24v653evcpxyr0mmhgwmsqxvrhfd",
      ],
      [
        "preimage",
        "ad047c02fe5f059c80877d794be88e47c644ebedfdfe663b289c9316db495f2d",
      ],
      [
        "description",
        '{"kind":9734,"created_at":1724685038,"content":"⚑Non-custodial zap from my Alby Hub","tags":[["p","15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e"],["relays","wss://purplepag.es/","wss://relay.getalby.com/v1","wss://nostr.mom/","wss://nostr.oxtr.dev/","wss://nos.lol/","wss://nostr.wine/","wss://relay.damus.io/","wss://relay.notoshi.win/","wss://eden.nostr.land/"],["amount","1000000"],["e","bcb2fcfe1c467c5ec8285e385c36ec13879709ced9d8800cb340ebf218c3210d"]],"pubkey":"0521db9531096dff700dcf410b01db47ab6598de7e5ef2c5a2bd7e1160315bf6","id":"57d8612007521c0b532b91af2498095a251e63f425187e6c95700fd0a6bab7d4","sig":"798d735118bcd14228a12b6d52423ff25bb4ed8cd5dacf2f5971ef573fdc3fc05fc793185e69682cca243d64f147a4498968a0bc288ae83e75c03e99f936a603"}',
      ],
    ],
  },
];

// https://github.com/nostr-protocol/nips/blob/master/57.md#appendix-f-validating-zap-receipts
/* A client can retrieve zap receipts on events and pubkeys using a NIP-01 filter, for example {"kinds": [9735], "#e": [...]}. Zaps MUST be validated using the following steps:

*/
// https://getalby.com/.well-known/nostr.json?name=rolznz
const nostrPubkey =
  "15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e";

// My pubkey in Damus is npub1zk6u7mxlflguqteghn8q7xtu47hyerruv6379c36l8lxzzr4x90q0gl6ef
// = 15b5cf6cdf4fd1c02f28bcce0f197cafae4c8c7c66a3e2e23af9fe610875315e

// My LNURLp Nostr Pubkey from https://getalby.com/.well-known/lnurlp/rolznz
const lnurlNostrPubkey =
  "79f00d3f5a19ec806189fcab03c1be4ff81d18ee4f653c88fac41fe03570f432";

for (const zap of zaps) {
  // 1. The zap receipt event's pubkey MUST be the same as the recipient's lnurl provider's nostrPubkey (retrieved in step 1 of the protocol flow).
  if (zap.pubkey !== lnurlNostrPubkey) {
    console.error("Incorrect pubkey for zap", zap.id);
    continue;
  }

  // check that the zap is for the right nostr user
  const pTag = zap.tags.find((tag) => tag[0] === "p");
  if (pTag?.[1] !== nostrPubkey) {
    console.error("Incorrect p tag for zap", zap.id);
    continue;
  }

  // The invoiceAmount contained in the bolt11 tag of the zap receipt MUST equal the amount tag of the zap request (if present).
  const bolt11 = zap.tags.find((tag) => tag[0] === "bolt11")?.[1];
  if (!bolt11) {
    console.error("No bolt11 tag for zap", zap.id);
    continue;
  }

  const zapRequestTagValue = zap.tags.find(
    (tag) => tag[0] === "description"
  )?.[1];
  if (!zapRequestTagValue) {
    console.error("No description tag for zap", zap.id);
    continue;
  }
  const zapRequest = JSON.parse(zapRequestTagValue);
  const zapRequestAmountTag = (zapRequest.tags as string[][]).find(
    (tag) => tag[0] === "amount"
  )?.[1];

  if (zapRequestAmountTag) {
    try {
      const invoice = new Invoice({
        pr: bolt11,
      });
      if (+zapRequestAmountTag != invoice.satoshi * 1000) {
        console.error(
          "Zap amount doesn't match invoice",
          +zapRequestAmountTag,
          invoice.satoshi,
          zap.id
        );
        continue;
      }
    } catch (error) {
      console.error("Failed to parse bolt11 for zap", zap.id, error);
      continue;
    }
  } else {
    console.log("No amount tag in zap request for zap", zap.id);
  }

  // The lnurl tag of the zap request (if present) SHOULD equal the recipient's lnurl.
  // None of the zaps have lnurl tags, so skipping.

  console.log("Zap OK", zap.id);
}
$ ts-node zaps.ts
Zap OK 326978e1885a2f9db30353e5d343314499db7365db2220b16ac9cf99f71de4a7
Zap OK 0cf681e27142e967770adaf27c98852128e788803e5d60725b974a48b0d3f6a8
Zap OK ec9aeae0da1aada7a7524aa832e4f3fc740d1e6fe527f23183acb98427460f10
Zap OK 0db388e1cebfb64e95cb42a3d960a5a71832afe0e62b2cff8ad52c08a2601281
Zap OK 4c75ab1e7098ccb7aeb8ff7d420236d357e58ccfb79fbe101704cb364987b68a
Done in 1.54s.
jb55 commented 2 months ago

ok I figured out why. our get_zap_description function attempts to get the zap_request from the description of the invoice if its not a descriptionhash invoice. I didn't realize you guys were not doing description hash to bake in the zap request into the invoice which is what most implementations do.

I will update damus to always get it from the tag regardless of invoice type. this logic is a bit dubious anyways since there should always be a description tag.

rolznz commented 2 months ago

Thank you! will zap when I get the new build :pray:

jb55 commented 2 months ago

PR:

jb55 commented 2 months ago

will push this out to purple testflight soon, I've also cherry-picked it to our next appstore release branch (1.10) which should be out soon

dmnyc commented 2 months ago

Just wanted to report that I can confirm Alby address zaps are now recorded in Damus.

Thanks for prioritizing this fix! image image