//
//  AnoncredsUtils.m
//  libindy-demo
//
//  Created by Kirill Neznamov on 24/05/2017.
//  Copyright © 2017 Kirill Neznamov. All rights reserved.
//

#import "AnoncredsUtils.h"
#import <XCTest/XCTest.h>
#import "TestUtils.h"
#import "WalletUtils.h"
#import "NSString+Validation.h"
#import "NSDictionary+JSON.h"

@interface AnoncredsUtils ()

@property (assign) BOOL isCommonWalletCreated;
@property (assign) IndyHandle walletHandle;
@property (strong) NSString* singletoneClaimdefJson;

@end

@implementation AnoncredsUtils


+ (AnoncredsUtils *)sharedInstance
{
    static AnoncredsUtils *instance = nil;
    static dispatch_once_t dispatch_once_block;
    
    dispatch_once(&dispatch_once_block, ^{
        instance = [AnoncredsUtils new];
        instance.isCommonWalletCreated = false;
        instance.walletHandle = 0;
    });
    
    return instance;
}

// MARK: - Default static values
+ (NSString *)commonMasterSecretName
{
    return @"common_master_secret_name";
}

+ (IndyHandle)walletHandle
{
    return 0;
}

+ (NSString *)claimDefJson
{
    return @"";
}

+ (NSString *)issuerDid
{
    return @"NcYxiDXkpYi6ov5FcYDi1e";
}

// MARK: - Json configurators
- (NSString *)getGvtSchemaJson:(NSNumber *)seqNo
{
    return [NSString stringWithFormat:@"{"
            "\"seqNo\":%@,"
            "\"data\":{"
                "\"name\":\"gvt\","
                "\"version\":\"1.0\","
                "\"keys\":[\"age\",\"sex\",\"height\",\"name\"]}"
            "}", seqNo];
}

- (NSString *)getClaimOfferJson:(NSString *)issuerDid
                    schemaSeqNo:(NSNumber *)schemaSeqNo
{
    return [NSString stringWithFormat:@"{"\
            "\"issuer_did\":\"%@\"," \
            "\"schema_seq_no\":%d" \
            "}", issuerDid,
                [schemaSeqNo intValue]
            ];
}

- (NSString *)getGvtClaimJson
{
    return [NSString stringWithFormat:@"{"\
            "\"sex\":[\"male\",\"5944657099558967239210949258394887428692050081607692519917050011144233115103\"],"\
            "\"name\":[\"Alex\",\"1139481716457488690172217916278103335\"],"\
            "\"height\":[\"175\",\"175\"],"\
            "\"age\":[\"28\",\"28\"]"\
            "}"];
}

- (NSString *)getXyzSchemaJson:(NSNumber *)schemaSeqNo
{
    return [NSString stringWithFormat:@"{"
            "\"seqNo\":%@,"
            "\"data\":{"
                "\"name\":\"xyz\","
                "\"version\":\"1.0\","
                "\"keys\":[\"status\",\"period\"]}"
            "}", schemaSeqNo];
}

- (NSString *)getXyzClaimJson
{
    return [NSString stringWithFormat:@"{"\
            "  \"status\":[\"partial\",\"51792877103171595686471452153480627530895\"],"\
            "  \"period\":[\"8\",\"8\"]"\
            "}"];
}

- (NSString *)getGvtClaimDef
{
    return @"{"
    "\"ref\":1,"
    "\"signature_type\":\"CL\","
    "\"data\":{"
    "\"primary\":{"
    "\"n\":\"83469852984476956871633111285697420678256060723156580163068122759469567425381600849138438902552107548539766861666590365174848381535291010418041757276710240953030842046122202402016906205924972182252295487319094577329593677544393592632224714613427822130473474379696616183721440743475053734247824037725487533789856061706740833324717788602268746116297029721621398888459529131593826880823126900285858832457134377949183677639585442886904844793608783831753240185678448312284269486845497720949217396146132958861735347072722092449280372574205841746312833280031873247525372459800132930201998084029506922484661426185450002143461\","
    "\"s\":\"36598527821865478336201608644402887021319976830281254144922838415193047189326184120876650311572665920640111967758238425066565864958446810892401358531545590342401290056836149703549220109981509774843525259400920352082531560361277411808530872594109525982462491998670199872903823657869742599086495624835178373073050767142081484206776345277546531080450529061958937980460303537107061046725579009809137197541389237618812289642185603461102513124991949835948586623327143696280240600789928383168220919049794681181861776889681393339729944540218566460627715413465709316412838042632482652979005394086058441511591756153781159121227\","
    "\"rms\":\"23836382972046033209463023456985914927629254782286444334728987813724281765327660893337383450653748691133061782449580026414785334582859397732571499366000805280757877601804441568263743400086744823885203441870748890135445454347495577599234477813361254101857848089907496868136222777024967328411073984887059985103475100012787049491016895625234124538894645853939428009610771524580099452739392988318945585946758355611531582519514003714424216836334706370901576611410508113637778751976890941210538254418937285168453791223070083264852447713991114719905171445881819334587600693321106919667204512182250084258986170095774914769107\","
    "\"r\":{"
    "\"age\":\"15428480888651268593621235736458685943389726269437020388313417035842991073151072061010468945249435098482625869236498750525662874597991333642865524104221652457788998109101749530884821300954337535472137069380551054204373136155978715752232238326100335828797868667735730830741789880726890058203015780792583471770404478023662994191588489722949795849990796063953164194432710764145637578113087142419634074378464118254848566088943085760634805903735300398689750649630456000759025366784986694635635510206166144055869823907120081668956271923743188342071093889666111639924270726451727101864752767708690529389259470017692442002767\","
    "\"name\":\"74008461204977705404956807338714891429397387365673402608947856456696416827848931951447004905350314563364442667940680669672331872875260077257474781261367591510351742401708951175978700805098470304211391452678992053755170054677498844656517106987419550598382601263743442309896367374279461481792679346472671426558385003925845431219156475505665973289508268634194964491418902859845301351562575713510002838692825728016254605821829245646855474149449192539144107522081712005891593405826343897070114168186645885993480245755494685105636168333649181939830898090651120926156152753918086493335382129839850609934233944397884745134858\","
    "\"sex\":\"40646934914193532541511585946883243600955533193734077080129022860038019728021796610599139377923881754708640252789475144625086755150150612623804964347576907276705600241268266301487516824189453869193926251791711672689649199860304727280764676403810510047397326018392955950249975529169980045664874433828266623495515931483137318724210483205730962036282580749206735450480976847188040030165278917936054139926609849181885654646269083459580415131952938813839182742590617440550773580790446467896469090164142755499827316294406540664375065617280568303837662431668218593808092907551353093044984225946834165309588512359379032847125\","
    "\"height\":\"60077310006190228182950362501472785016827894350517184186566050586806482282196022414888288252599211919680339352529750982779980002923071031258837648242708410943080288964834346858544959217874890558006056551949543916094446891954292824146212277550956558692224016968153138097595802008943263818064605343108607131298420107448075252583276684858815371561492996587478784667827675142382692061950832554910690663724101360454494298013020706080246986445114235542283015624510836206522238238728405826712730615187235709554561445384409566940622412591208469650855059870671771721035756205878334354791247751663679130847366069215369484993653\"},"
    "\"rctxt\":\"36378575722516953828830668112614685244571602424420162720244033008706985740860180373728219883172046821464173434592331868657297711725743060654773725561634332269874655603697872022630999786617840856366807034806938874090561725454026277048301648000835861491030368037108847175790943895107305383779598585532854170748970999977490244057635358075906501562932970296830906796719844887269636297064678777638050708353254894155336111384638276041851818109156194135995350001255928374102089400812445206030019103440866343736761861049159446083221399575945128480681798837648578166327164995640582517916904912672875184928940552983440410245037\","
    "\"z\":\"65210811645114955910002482704691499297899796787292244564644467629838455625296674951468505972574512639263601600908664306008863647466643899294681985964775001929521624341158696866597713112430928402519124073453804861185882073381514901830347278653016300430179820703804228663001232136885036042101307423527913402600370741689559698469878576457899715687929448757963179899698951620405467976414716277505767979494596626867505828267832223147104774684678295400387894506425769550011471322118172087199519094477785389750318762521728398390891214426117908390767403438354009767291938975195751081032073309083309746656253788033721103313036\""
    "}"
    "}"
    "}";
}

- (NSString *)getGvtClaimRequest
{
    return @"{"\
        "\"claim_request\":{"\
            "\"prover_did\":\"CnEDk9HrMnmiHXEV1WFgbVCRteYnPqsJwrTdcZaNhFVW\","\
            "\"u\":\"72052674960029442327236458752017934128206007798774128392572211954456711136771871346204637748253860917837147111221378456345006764308173447177933384497678611527908801900335623480700015849806575534757455484512742315652166882850683721692964547448843598104385874050447011820051099399087175505815748958014671544911179795524159951193233504921329404534187047046492036161628814022862661479869322137573048331473599346645871295570237032991261433025344456232326409789544299441933427561947291495434188942844516539974096858281005872862193803356400358925349350554630231733687344283622639185011395343616612151755685912869590344206893\","\
            "\"ur\":null\"},"\
        "\"issuer_did\":\"NcYxiDXkpYi6ov5FcYDi1e\","\
        "\"claim_def_seq_no\":1"\
    "}";
}

- (NSString *)getClaimDefIdForIssuerDid:(NSString *)issuerDid
                            schemaSeqNo:(NSNumber *)schemaSeqNo
{
    return [NSString stringWithFormat:@"%@:%@",issuerDid, [schemaSeqNo stringValue]];
}

// MARK: issuer claim
- (NSError *)issuerCreateClaimWithWalletHandle:(IndyHandle)walletHandle
                                  claimReqJson:(NSString *)claimReqJson
                                     claimJson:(NSString *)claimJson
                                  outClaimJson:(NSString **)xClaimJson
                         outRevocRegUpdateJSON:(NSString **)revocRegUpdateJSON
{
    __block NSError *err = nil;
    __block NSString *outClaimJson;
    __block NSString *outRevocRegUpdateJSON;
    XCTestExpectation* completionExpectation = nil;
    
    completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [IndyAnoncreds  issuerCreateClaimWithWalletHandle:walletHandle
                                                          claimReqJSON:claimReqJson
                                                             claimJSON:claimJson
                                                         revocRegSeqNo:@(-1)
                                                        userRevocIndex:@(-1)
                                                            completion:^(NSError *error, NSString *revocRegUpdateJSON, NSString *claimJSON)
                    {
                        err = error;
                        outRevocRegUpdateJSON = revocRegUpdateJSON;
                        outClaimJson = claimJSON;
                        [completionExpectation fulfill];
                    }];
    
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils shortTimeout]];
    
    if (xClaimJson) {*xClaimJson = outClaimJson;}
    if (revocRegUpdateJSON) {*revocRegUpdateJSON = outRevocRegUpdateJSON;}
    return err;
}

- (NSError *)issuerCreateClaimDefinifionWithWalletHandle:(IndyHandle)walletHandle
                                               issuerDid:(NSString *)issuerDid
                                              schemaJson:(NSString *)schemaJson
                                           signatureType:(NSString *)signatureType
                                          createNonRevoc:(BOOL)createNonRevoc
                                            claimDefJson:(NSString **)claimDefJson;
{
    __block NSError *err = nil;
    __block NSString *outClaimDefJson = nil;
    XCTestExpectation *completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [IndyAnoncreds  issuerCreateAndStoreClaimDefWithWalletHandle:walletHandle
                                                                        issuerDid:issuerDid
                                                                       schemaJSON:schemaJson
                                                                    signatureType:signatureType
                                                                   createNonRevoc:createNonRevoc
                                                                       completion:^(NSError *error, NSString *claimDefJSON)
                    {
                        err = error;
                        outClaimDefJson = claimDefJSON;
                        
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    
    if ( claimDefJson ) { *claimDefJson = outClaimDefJson; }
    
    return err;
}

- (NSArray *)getUniqueClaimsFrom:(NSDictionary *)proofClaims
{
    NSMutableArray* uniqueClaims =  [[NSMutableArray alloc] init];
    
    for (NSDictionary* claims in proofClaims.allValues )
    {
        
        for (NSArray* claim in claims.allValues)
        {
            if ( ![uniqueClaims containsObject: claim[0]] )
            {
                [uniqueClaims addObject:claim[0]];
            }
        }
    }
    
    NSArray* res = [NSArray arrayWithArray:uniqueClaims];
    return res;
    
}

- (NSError *)proverCreateMasterSecret:(IndyHandle)walletHandle
                     masterSecretName:(NSString *)name
{
    __block NSError *err = nil;
    XCTestExpectation* completionExpectation = nil;
    
    completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [IndyAnoncreds proverCreateMasterSecretWithWalletHandle:walletHandle
                                                            masterSecretName:name
                                                                  completion:^(NSError *error)
                    {
                        err = error;
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    return err;
}

- (NSError *)proverStoreClaimOffer:(IndyHandle)walletHandle
                    claimOfferJson:(NSString *)str
{
    __block NSError *err = nil;
    XCTestExpectation* completionExpectation = nil;
    
    completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [IndyAnoncreds proverStoreClaimOfferWithWalletHandle:walletHandle
                                                           claimOfferJSON:str
                                                               completion: ^(NSError *error)
                    {
                        err = error;
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    
    return err;
    
}

- (NSError *)proverGetClaimOffers:(IndyHandle)walletHandle
                       filterJson:(NSString *)filterJson
               outClaimOffersJSON:(NSString **)outJson
{
    __block NSString *json;
    __block NSError *err = nil;
    XCTestExpectation* completionExpectation = nil;
    
    completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [ IndyAnoncreds proverGetClaimOffersWithWalletHandle:walletHandle
                                                               filterJSON:filterJson
                                                               completion:^(NSError *error, NSString *claimOffersJSON)
                    {
                        err = error;
                        json = claimOffersJSON;
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    
    if (outJson) { *outJson = json; }
    return err;
}

- (NSError *)proverCreateAndStoreClaimReq:(IndyHandle)walletHandle
                                proverDid:(NSString *)pd
                           claimOfferJson:(NSString *)coj
                             claimDefJson:(NSString *)cdj
                         masterSecretName:(NSString *)name
                          outClaimReqJson:(NSString **)outJson
{
    __block NSError *err = nil;
    __block NSString *json;
    XCTestExpectation* completionExpectation = nil;
    
    completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [ IndyAnoncreds proverCreateAndStoreClaimReqWithWalletHandle: walletHandle
                                                                        proverDid:pd
                                                                   claimOfferJSON:coj
                    
                                                                     claimDefJSON:cdj
                                                                 masterSecretName:name
                                                                       completion:^(NSError* error, NSString* claimReqJSON)
                    {
                        err = error;
                        json = claimReqJSON;
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    
    if (outJson) { *outJson = json; }
    return err;
}



- (NSError *) proverStoreClaimWithWalletHandle:(IndyHandle)walletHandle
                                    claimsJson:(NSString *)str
{
    __block NSError *err = nil;
    XCTestExpectation* completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [IndyAnoncreds proverStoreClaimWithWalletHandle:walletHandle
                                                          claimsJSON:str
                                                          completion:^(NSError *error)
                    {
                        XCTAssertEqual(err.code, Success, @"proverStoreClaim failed!");
                        err = error;
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    
    return err;
}

- (NSError *)proverGetClaimsForProofReqWithWalletHandle:(IndyHandle)walletHandle
                                       proofRequestJson:(NSString *)str
                                          outClaimsJson:(NSString **)outClaimsJson
{
    __block NSError *err = nil;
    __block NSString *outJson;
    XCTestExpectation* completionExpectation = nil;
    
    completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [IndyAnoncreds proverGetClaimsForProofReqWithWalletHandle:walletHandle
                                                                  proofReqJSON:str
                                                                    completion:^(NSError *error, NSString *claimsJSON)
                    {
                        err = error;
                        outJson = claimsJSON;
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    
    if (outClaimsJson) { *outClaimsJson = outJson; }
    
    return err;
}

- (NSError *)proverGetClaimsForWalletHandle:(IndyHandle)walletHandle
                                 filterJson:(NSString *)filterJson
                              outClaimsJson:(NSString **)claimsJson
{
    __block NSError *err = nil;
    __block NSString *outJson;
    XCTestExpectation* completionExpectation = nil;
    
    completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [IndyAnoncreds proverGetClaimsWithWalletHandle:walletHandle
                                                         filterJSON:filterJson
                                                         completion:^(NSError *error, NSString *claimsJSON)
                    {
                        err = error;
                        outJson = claimsJSON;
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    
    if (claimsJson) { *claimsJson = outJson;}
    
    return err;
}

- (NSError *)proverCreateProofWithWalletHandle:(IndyHandle)walletHandle
                                  proofReqJson:(NSString *)proofReqJson
                           requestedClaimsJson:(NSString *)requestedClaimsJson
                                   schemasJson:(NSString *)schemasJson
                              masterSecretName:(NSString *)masterSecreteName
                                 claimDefsJson:(NSString *)claimDefsJson
                                 revocRegsJson:(NSString *)revocRegsJson
                                  outProofJson:(NSString **)outProofJson
{
    __block NSError *err = nil;
    __block NSString *outJson;
    XCTestExpectation* completionExpectation = nil;
    
    completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [IndyAnoncreds proverCreateProofWithWalletHandle:walletHandle
                                                         proofReqJSON:proofReqJson
                                                  requestedClaimsJSON:requestedClaimsJson
                                                          schemasJSON:schemasJson
                                                     masterSecretName:masterSecreteName
                                                        claimDefsJSON:claimDefsJson
                                                        revocRegsJSON:revocRegsJson
                                                           completion:^(NSError *error, NSString *proofJSON)
                    {
                        err = error;
                        outJson = proofJSON;
                        
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    
    if (outProofJson) { *outProofJson = outJson; }
    return err;
}

- (NSError *)verifierVerifyProof:(NSString *)proofRequestJson
                       proofJson:(NSString *)proofJson
                     schemasJson:(NSString *)schemasJson
                   claimDefsJson:(NSString *)claimDefsJson
                   revocRegsJson:(NSString *)revocRegsJson
                        outValid:(BOOL *)isValid
{
    __block NSError *err = nil;
    XCTestExpectation *completionExpectation = nil;
    
    completionExpectation = [[ XCTestExpectation alloc] initWithDescription: @"completion finished"];
    
    NSError *ret = [IndyAnoncreds verifierVerifyProofWithWalletHandle:proofRequestJson
                                                              proofJSON:proofJson
                                                            schemasJSON:schemasJson
                                                          claimDefsJSON:claimDefsJson
                                                          revocRegsJSON:revocRegsJson
                                                             completion:^(NSError *error, BOOL valid)
                    {
                        err = error;
                        if(isValid)
                        {
                            *isValid = valid;
                        }
                        [completionExpectation fulfill];
                    }];
    
    if( ret.code != Success)
    {
        return ret;
    }
    
    [self waitForExpectations: @[completionExpectation] timeout:[TestUtils defaultTimeout]];
    return err;
    
}

- (NSError *)initializeCommonWalletAndReturnHandle:(IndyHandle *)walletHandle
                                      claimDefJson:(NSString **)claimDefJson
{
    if (self.isCommonWalletCreated)
    {
        if (walletHandle)
        {
            *walletHandle = self.walletHandle;
        }
        if (claimDefJson)
        {
            *claimDefJson = _singletoneClaimdefJson;
        }
        return [NSError errorWithDomain:@""
                                   code:Success
                               userInfo:nil];
    }
    
    [TestUtils cleanupStorage];
    
    XCTAssertTrue(5 == 3, @"FALSE!!!!");
    
    ////TODO Need clean after tests but not exists After function in Cargo
    NSError *ret;
    
    // 1. Create and open wallet
    self.walletHandle = 0;
    IndyHandle tempWalletHandle = 0;
    ret = [[WalletUtils sharedInstance] createAndOpenWalletWithPoolName:@"pool1"
                                                                  xtype:nil
                                                                 handle:&tempWalletHandle];
    XCTAssertEqual(ret.code, Success, @"WalletUtils::createAndOpenWalletWithPoolName failed");
    if (ret.code != Success) {return ret;}
    
    //2. Create GVT ClaimDefinition
    NSNumber *seqNo = @(1);
    NSString *schema = [self getGvtSchemaJson:seqNo];
    NSString *tempClaimDefJson;
    ret = [self issuerCreateClaimDefinifionWithWalletHandle:tempWalletHandle
                                                  issuerDid:[AnoncredsUtils issuerDid]
                                                 schemaJson:schema
                                              signatureType:nil
                                             createNonRevoc:false
                                               claimDefJson:&tempClaimDefJson];
    XCTAssertEqual(ret.code, Success, @"issuerCreateClaimDefinifionWithWalletHandle failed");
    
    if (ret.code != Success) {return ret;}
    XCTAssertTrue([tempClaimDefJson isValid], @"invalid tempClaimDefJson: %@", tempClaimDefJson);
    
    //3. Store three claim offers
    NSString *claimOfferJson1 = [self getClaimOfferJson:[AnoncredsUtils issuerDid]
                                            schemaSeqNo:@(1)];
    NSString *claimOfferJson2 = [self getClaimOfferJson:[AnoncredsUtils issuerDid]
                                            schemaSeqNo:@(2)];
    NSString *claimOfferJson3 = [self getClaimOfferJson:@"CnEDk9HrMnmiHXEV1WFgbVCRteYnPqsJwrTdcZaNhFVW"
                                            schemaSeqNo:@(2)];
    
    ret = [self proverStoreClaimOffer:tempWalletHandle claimOfferJson:claimOfferJson1];
    XCTAssertEqual(ret.code, Success, @"proverStoreClaimOffer failed for claimOfferJson1");
    
    ret = [self proverStoreClaimOffer:tempWalletHandle claimOfferJson:claimOfferJson2];
    XCTAssertEqual(ret.code, Success, @"proverStoreClaimOffer failed for claimOfferJson2");
    
    ret = [self proverStoreClaimOffer:tempWalletHandle claimOfferJson:claimOfferJson3];
    XCTAssertEqual(ret.code, Success, @"proverStoreClaimOffer failed for claimOfferJson3");
    
    //4. Create MasterSecret
    ret = [self proverCreateMasterSecret:tempWalletHandle
                        masterSecretName:[AnoncredsUtils commonMasterSecretName]];
    XCTAssertEqual(ret.code, Success, @"proverCreateMasterSecret failed");
    
    //5. Create and Store Claim Request
    NSString *claimRequest;
    ret = [self proverCreateAndStoreClaimReq:tempWalletHandle
                                   proverDid:@"HEJ9gvWX64wW7UD"
                              claimOfferJson:claimOfferJson1
                                claimDefJson:tempClaimDefJson
                            masterSecretName:[AnoncredsUtils commonMasterSecretName]
                             outClaimReqJson:&claimRequest];
    
    XCTAssertEqual(ret.code, Success, @"proverCreateAndStoreClaimReq failed for claimOfferJson1");
    XCTAssertTrue([claimRequest isValid], @"invalid claim request: %@", claimRequest);
    
    if (ret.code != Success) {return ret;}
    
    NSString *claimJson = [self getGvtClaimJson];
    
    //6. Create Claim
    NSString *xClaimJson;
    ret = [self issuerCreateClaimWithWalletHandle:tempWalletHandle
                                     claimReqJson:claimRequest
                                        claimJson:claimJson
                                     outClaimJson:&xClaimJson
                            outRevocRegUpdateJSON:nil];
    XCTAssertEqual(ret.code, Success, @"issuerCreateClaimWithWalletHandle failed");
    XCTAssertTrue([xClaimJson isValid], @"invalid xClaimJson: %@", xClaimJson);
    
    // 7. Store claim
    ret = [self proverStoreClaimWithWalletHandle:tempWalletHandle
                                      claimsJson:xClaimJson];
    XCTAssertEqual(ret.code, Success, @"proverStoreClaimWithWalletHandle failed");
    
    if (walletHandle){ *walletHandle = tempWalletHandle;}
    if (claimDefJson){ *claimDefJson = tempClaimDefJson;}
    self.walletHandle = tempWalletHandle;
    _singletoneClaimdefJson = tempClaimDefJson;
    
    self.isCommonWalletCreated = true;
    
    return ret;
}

@end
